1 28 29 package com.caucho.relaxng.program; 30 31 import com.caucho.relaxng.RelaxException; 32 import com.caucho.util.CharBuffer; 33 import com.caucho.util.L10N; 34 import com.caucho.xml.QName; 35 36 import java.util.ArrayList ; 37 import java.util.HashSet ; 38 import java.util.Iterator ; 39 import java.util.NoSuchElementException ; 40 41 44 public class GroupItem extends Item { 45 protected final static L10N L = new L10N(GroupItem.class); 46 47 private Item _first; 48 private Item _second; 49 50 private GroupItem(Item first, Item second) 51 { 52 _first = first; 53 _second = second; 54 } 55 56 public static Item create(Item first, Item second) 57 { 58 if (first == null || second == null) 59 return null; 60 else if (first instanceof EmptyItem) 61 return second; 62 else if (second instanceof EmptyItem) 63 return first; 64 else if (first instanceof GroupItem) { 65 GroupItem firstSeq = (GroupItem) first; 66 67 return create(firstSeq.getFirst(), create(firstSeq.getSecond(), second)); 68 } 69 else if (first instanceof InElementItem) { 70 InElementItem firstElt = (InElementItem) first; 71 72 return InElementItem.create(firstElt.getFirst(), 73 create(firstElt.getSecond(), second)); 74 } 75 else 76 return new GroupItem(first, second); 77 } 78 79 Item getFirst() 80 { 81 return _first; 82 } 83 84 Item getSecond() 85 { 86 return _second; 87 } 88 89 92 public void firstSet(HashSet <QName> set) 93 { 94 _first.firstSet(set); 95 if (_first.allowEmpty()) 96 _second.firstSet(set); 97 } 98 99 102 public void requiredFirstSet(HashSet <QName> set) 103 { 104 if (! _first.allowEmpty()) 105 _first.requiredFirstSet(set); 106 else 107 _second.requiredFirstSet(set); 108 } 109 110 113 public Iterator <Item> getItemsIterator() 114 { 115 if ( _first == null && _second == null ) 116 return emptyItemIterator(); 117 118 return new Iterator <Item>() { 119 private int _cnt; 120 121 public boolean hasNext() 122 { 123 if (_cnt == 0) 124 return _first != null || _second != null; 125 else if (_cnt == 1) 126 return _first != null && _second != null; 127 else 128 return false; 129 } 130 131 public Item next() 132 { 133 if (!hasNext()) 134 throw new NoSuchElementException (); 135 136 if (_cnt++ == 0) 137 return _first != null ? _first : _second; 138 else 139 return _second; 140 } 141 142 public void remove() 143 { 144 throw new UnsupportedOperationException (); 145 } 146 }; 147 } 148 149 150 158 public Item startElement(QName name) 159 throws RelaxException 160 { 161 Item nextHead = _first.startElement(name); 162 163 Item tail = GroupItem.create(nextHead, _second); 164 165 if (_first.allowEmpty()) 166 return ChoiceItem.create(tail, _second.startElement(name)); 167 else 168 return tail; 169 } 170 171 178 public Item text(String string) 179 throws RelaxException 180 { 181 Item nextHead = _first.text(string); 182 183 Item tail = GroupItem.create(nextHead, _second); 184 185 if (_first.allowEmpty()) 186 return ChoiceItem.create(tail, _second.text(string)); 187 else 188 return tail; 189 } 190 191 194 public void attributeSet(HashSet <QName> set) 195 { 196 _first.attributeSet(set); 197 _second.attributeSet(set); 198 } 199 200 208 public boolean allowAttribute(QName name, String value) 209 throws RelaxException 210 { 211 return (_first.allowAttribute(name, value) || 212 _second.allowAttribute(name, value)); 213 } 214 215 223 public Item setAttribute(QName name, String value) 224 throws RelaxException 225 { 226 Item first = _first.setAttribute(name, value); 227 Item second = _second.setAttribute(name, value); 228 229 if (first == _first && second == _second) 230 return this; 231 else if (first == null) 232 return second; 233 else if (second == null) 234 return first; 235 else 236 return create(first, second); 237 } 238 239 242 public Item attributeEnd() 243 { 244 Item first = _first.attributeEnd(); 245 Item second = _second.attributeEnd(); 246 247 if (first == null || second == null) 248 return null; 249 else if (first == _first && second == _second) 250 return this; 251 else 252 return create(first, second); 253 } 254 255 258 public boolean allowEmpty() 259 { 260 return _first.allowEmpty() && _second.allowEmpty(); 261 } 262 263 272 public boolean allowsElement(QName name) 273 { 274 return _first.allowsElement(name) || _second.allowsElement(name); 275 } 276 277 280 public String toSyntaxDescription(int depth) 281 { 282 if (_second instanceof EmptyItem) 283 return _first.toSyntaxDescription(depth); 284 285 ArrayList <Item> items = new ArrayList <Item>(); 286 287 Item item = this; 288 while (item instanceof GroupItem) { 289 GroupItem groupItem = (GroupItem) item; 290 291 items.add(groupItem._first); 292 293 item = groupItem._second; 294 } 295 296 if (item != null && ! (item instanceof EmptyItem)) 297 items.add(item); 298 299 CharBuffer cb = CharBuffer.allocate(); 300 301 cb.append('('); 302 303 boolean isSimple = true; 304 for (int i = 0; i < items.size(); i++) { 305 item = items.get(i); 306 307 if (i == 0) { 308 cb.append(item.toSyntaxDescription(depth + 1)); 309 isSimple = item.isSimpleSyntax(); 310 } 311 else 312 isSimple = addSyntaxItem(cb, item, depth, isSimple); 313 314 if (i + 1 < items.size()) { 315 Item next = items.get(i + 1); 316 317 if (next instanceof ZeroOrMoreItem) { 318 ZeroOrMoreItem starItem = (ZeroOrMoreItem) next; 319 320 if (starItem.getItem().equals(item)) { 321 cb.append("+"); 322 i++; 323 324 if (i == 1 && i == items.size() - 1) { 325 cb.delete(0, 1); 326 327 return cb.close(); 328 } 329 } 330 } 331 } 332 } 333 334 cb.append(')'); 335 336 return cb.close(); 337 } 338 339 342 private boolean addSyntaxItem(CharBuffer cb, Item item, 343 int depth, boolean isSimple) 344 { 345 if (! item.isSimpleSyntax()) 346 isSimple = false; 347 348 if (isSimple) { 349 cb.append(", "); 350 } 351 else { 352 cb.append(","); 353 addSyntaxNewline(cb, depth + 1); 354 } 355 356 cb.append(item.toSyntaxDescription(depth + 1)); 357 358 return isSimple; 359 } 360 361 364 protected boolean isSimpleSyntax() 365 { 366 return (_second instanceof EmptyItem) && _first.isSimpleSyntax(); 367 } 368 369 372 public int hashCode() 373 { 374 return _first.hashCode() * 65521 + _second.hashCode(); 375 } 376 377 380 public boolean equals(Object o) 381 { 382 if (! (o instanceof GroupItem)) 383 return false; 384 385 GroupItem seq = (GroupItem) o; 386 387 return _first.equals(seq._first) && _second.equals(seq._second); 388 } 389 390 public String toString() 391 { 392 return "GroupItem[" + _first + ", " + _second + "]"; 393 } 394 } 395 396 | Popular Tags |