1 29 30 package com.caucho.relaxng.program; 31 32 import com.caucho.relaxng.RelaxException; 33 import com.caucho.util.CharBuffer; 34 import com.caucho.util.L10N; 35 import com.caucho.xml.QName; 36 37 import java.util.ArrayList ; 38 import java.util.HashSet ; 39 import java.util.Iterator ; 40 41 44 public class ChoiceItem extends Item { 45 protected final static L10N L = new L10N(ChoiceItem.class); 46 47 private ArrayList <Item> _items = new ArrayList <Item>(); 48 49 private boolean _allowEmpty = false; 50 51 public ChoiceItem() 52 { 53 } 54 55 public static Item create(Item left, Item right) 56 { 57 ChoiceItem choice = new ChoiceItem(); 58 choice.addItem(left); 59 choice.addItem(right); 60 61 return choice.getMin(); 62 } 63 64 public void addItem(Item item) 65 { 66 if (item == null) 67 return; 68 else if (item instanceof EmptyItem) { 69 _allowEmpty = true; 70 return; 71 } 72 else if (item instanceof ChoiceItem) { 73 ChoiceItem choice = (ChoiceItem) item; 74 75 if (choice._allowEmpty) 76 _allowEmpty = true; 77 78 for (int i = 0; i < choice._items.size(); i++) 79 addItem(choice._items.get(i)); 80 81 return; 82 } 83 84 for (int i = 0; i < _items.size(); i++) { 85 Item subItem = _items.get(i); 86 87 if (item.equals(subItem)) 88 return; 89 90 if (item instanceof InElementItem && 91 subItem instanceof InElementItem) { 92 InElementItem elt1 = (InElementItem) item; 93 InElementItem elt2 = (InElementItem) subItem; 94 95 if (elt1.getElementItem().equals(elt2.getElementItem())) { 96 subItem = InElementItem.create(elt1.getElementItem(), 97 create(elt1.getContinuationItem(), 98 elt2.getContinuationItem())); 99 _items.remove(i); 100 addItem(subItem); 101 return; 102 } 103 } 104 105 if (item instanceof GroupItem && 106 subItem instanceof GroupItem) { 107 GroupItem group1 = (GroupItem) item; 108 GroupItem group2 = (GroupItem) subItem; 109 110 if (group1.getFirst().equals(group2.getFirst())) { 111 subItem = GroupItem.create(group1.getFirst(), 112 create(group1.getSecond(), 113 group2.getSecond())); 114 _items.remove(i); 115 addItem(subItem); 116 return; 117 } 118 } 119 } 120 121 _items.add(item); 122 } 123 124 public Item getMin() 125 { 126 if (! _allowEmpty && _items.size() == 0) 127 return null; 128 else if (_allowEmpty && _items.size() == 0) 129 return EmptyItem.create(); 130 else if (_items.size() == 1 && 131 (! _allowEmpty || _items.get(0).allowEmpty())) 132 return _items.get(0); 133 else 134 return this; 135 } 136 137 140 public void firstSet(HashSet <QName> set) 141 { 142 for (int i = 0; i < _items.size(); i++) 143 _items.get(i).firstSet(set); 144 } 145 146 149 public void requiredFirstSet(HashSet <QName> set) 150 { 151 if (allowEmpty()) 152 return; 153 154 for (int i = 0; i < _items.size(); i++) 155 _items.get(i).requiredFirstSet(set); 156 } 157 158 161 public boolean allowEmpty() 162 { 163 if (_allowEmpty) 164 return true; 165 166 for (int i = 0; i < _items.size(); i++) 167 if (_items.get(i).allowEmpty()) 168 return true; 169 170 return false; 171 } 172 173 176 public Item interleaveContinuation(Item cont) 177 { 178 ChoiceItem item = new ChoiceItem(); 179 180 for (int i = 0; i < _items.size(); i++) 181 item.addItem(_items.get(i).interleaveContinuation(cont)); 182 183 return item.getMin(); 184 } 185 186 189 public Item inElementContinuation(Item cont) 190 { 191 ChoiceItem item = new ChoiceItem(); 192 193 for (int i = 0; i < _items.size(); i++) 194 item.addItem(_items.get(i).inElementContinuation(cont)); 195 196 return item.getMin(); 197 } 198 199 202 public Item groupContinuation(Item cont) 203 { 204 ChoiceItem item = new ChoiceItem(); 205 206 for (int i = 0; i < _items.size(); i++) 207 item.addItem(_items.get(i).groupContinuation(cont)); 208 209 return item.getMin(); 210 } 211 212 215 public Iterator <Item> getItemsIterator() 216 { 217 if ( _items.size() == 0 ) 218 return emptyItemIterator(); 219 else 220 return _items.iterator(); 221 } 222 223 226 public Item startElement(QName name) 227 throws RelaxException 228 { 229 Item result = null; 230 ChoiceItem choice = null; 231 232 for (int i = 0; i < _items.size(); i++) { 233 Item next = _items.get(i).startElement(name); 234 235 if (next == null) { 236 } 237 else if (result == null) 238 result = next; 239 else { 240 if (choice == null) { 241 choice = new ChoiceItem(); 242 choice.addItem(result); 243 } 244 245 choice.addItem(next); 246 } 247 } 248 249 if (choice != null) 250 return choice.getMin(); 251 else 252 return result; 253 } 254 255 258 public void attributeSet(HashSet <QName> set) 259 { 260 for (int i = 0; i < _items.size(); i++) 261 _items.get(i).attributeSet(set); 262 } 263 264 272 public boolean allowAttribute(QName name, String value) 273 throws RelaxException 274 { 275 for (int i = _items.size() - 1; i >= 0; i--) 276 if (_items.get(i).allowAttribute(name, value)) 277 return true; 278 279 return false; 280 } 281 282 290 public Item setAttribute(QName name, String value) 291 throws RelaxException 292 { 293 if (! allowAttribute(name, value)) 294 return this; 295 296 ChoiceItem choice = new ChoiceItem(); 297 298 if (_allowEmpty) 299 choice.addItem(EmptyItem.create()); 300 301 for (int i = _items.size() - 1; i >= 0; i--) { 302 Item next = _items.get(i).setAttribute(name, value); 303 304 if (next == null) 305 return null; 306 307 choice.addItem(next); 308 } 309 310 return choice.getMin(); 311 } 312 313 316 public Item attributeEnd() 317 { 318 ChoiceItem choice = new ChoiceItem(); 319 320 if (_allowEmpty) 321 choice._allowEmpty = true; 322 323 for (int i = _items.size() - 1; i >= 0; i--) { 324 Item next = _items.get(i).attributeEnd(); 325 326 if (next == null) 327 continue; 328 329 choice.addItem(next); 330 } 331 332 if (choice.equals(this)) 333 return this; 334 else 335 return choice.getMin(); 336 } 337 338 341 public Item text(String data) 342 throws RelaxException 343 { 344 Item result = null; 345 ChoiceItem choice = null; 346 347 for (int i = 0; i < _items.size(); i++) { 348 Item next = _items.get(i).text(data); 349 350 if (next == null) { 351 } 352 else if (result == null) 353 result = next; 354 else { 355 if (choice == null) { 356 choice = new ChoiceItem(); 357 choice.addItem(result); 358 } 359 360 choice.addItem(next); 361 } 362 } 363 364 if (choice != null) 365 return choice.getMin(); 366 else 367 return result; 368 } 369 370 373 public Item endElement() 374 throws RelaxException 375 { 376 ChoiceItem choice = new ChoiceItem(); 377 378 if (_allowEmpty) 379 choice._allowEmpty = true; 380 381 for (int i = _items.size() - 1; i >= 0; i--) { 382 Item next = _items.get(i).endElement(); 383 384 if (next == null) 385 continue; 386 387 choice.addItem(next); 388 } 389 390 if (choice.equals(this)) 391 return this; 392 else 393 return choice.getMin(); 394 } 395 396 399 public int hashCode() 400 { 401 int hash = 37; 402 403 for (int i = 0; i < _items.size(); i++) 404 hash += _items.get(i).hashCode(); 405 406 return hash; 407 } 408 409 412 public boolean equals(Object o) 413 { 414 if (this == o) 415 return true; 416 417 if (! (o instanceof ChoiceItem)) 418 return false; 419 420 ChoiceItem choice = (ChoiceItem) o; 421 422 return isSubset(choice) && choice.isSubset(this); 423 } 424 425 private boolean isSubset(ChoiceItem item) 426 { 427 if (_items.size() != item._items.size()) 428 return false; 429 430 for (int i = 0; i < _items.size(); i++) { 431 Item subItem = _items.get(i); 432 433 if (! item._items.contains(subItem)) 434 return false; 435 } 436 437 return true; 438 } 439 440 449 public boolean allowsElement(QName name) 450 { 451 for (int i = 0; i < _items.size(); i++) { 452 Item subItem = _items.get(i); 453 454 if (subItem.allowsElement(name)) 455 return true; 456 } 457 458 return false; 459 } 460 461 464 public String toSyntaxDescription(int depth) 465 { 466 CharBuffer cb = CharBuffer.allocate(); 467 468 if (_items.size() > 1) 469 cb.append("("); 470 471 boolean isSimple = true; 472 for (int i = 0; i < _items.size(); i++) { 473 Item item = _items.get(i); 474 if (! item.isSimpleSyntax()) 475 isSimple = false; 476 477 if (i == 0) { 478 if (! isSimple) 479 cb.append(" "); 480 } 481 else if (isSimple) { 482 cb.append(" | "); 483 } 484 else { 485 addSyntaxNewline(cb, depth); 486 cb.append("| "); 487 } 488 489 cb.append(item.toSyntaxDescription(depth + 2)); 490 } 491 492 if (_items.size() > 1) 493 cb.append(')'); 494 495 if (_allowEmpty) 496 cb.append('?'); 497 498 return cb.close(); 499 } 500 501 504 protected boolean isSimpleSyntax() 505 { 506 return (_items.size() == 1) && _items.get(0).isSimpleSyntax(); 507 } 508 509 public String toString() 510 { 511 StringBuffer sb = new StringBuffer (); 512 513 sb.append("ChoiceItem["); 514 for (int i = 0; i < _items.size(); i++) { 515 if (i != 0) 516 sb.append(", "); 517 sb.append(_items.get(i)); 518 } 519 520 sb.append("]"); 521 522 return sb.toString(); 523 } 524 } 525 526 | Popular Tags |