1 19 20 package org.netbeans.modules.xml.dtd.grammar; 21 22 import java.util.*; 23 import javax.swing.Icon ; 24 25 import org.w3c.dom.*; 26 27 import org.openide.ErrorManager; 28 29 import org.netbeans.modules.xml.api.model.*; 30 import org.netbeans.modules.xml.spi.dom.*; 31 32 39 class DTDGrammar implements ExtendedGrammarQuery { 40 41 private Map elementDecls, attrDecls; 43 44 private Map contentModels; 47 48 private Map attrEnumerations; 50 51 private Map defaultAttributeValues; 53 54 private Set entities, notations; 55 56 57 private Set emptyElements; 58 59 private List resolvedEntities; 60 61 62 DTDGrammar(Map elementDecls, Map contentModels, Map attrDecls, Map attrDefs, Map enums, Set entities, Set notations, Set emptyElements) { 63 this.elementDecls = elementDecls; 64 this.attrDecls = attrDecls; 65 this.entities = entities; 66 this.notations = notations; 67 this.attrEnumerations = enums; 68 this.contentModels = contentModels; 69 this.defaultAttributeValues = attrDefs; 70 this.emptyElements = emptyElements; 71 } 72 73 void setResolvedEntities(List resolvedEntities) { 74 this.resolvedEntities = resolvedEntities; 75 } 76 77 public List getResolvedEntities() { 78 return resolvedEntities; 79 } 80 81 85 public Enumeration queryEntities(String prefix) { 86 if (entities == null) return org.openide.util.Enumerations.empty(); 87 88 LinkedList list = new LinkedList(); 89 Iterator it = entities.iterator(); 90 while ( it.hasNext()) { 91 String next = (String ) it.next(); 92 if (next.startsWith(prefix)) { 93 list.add (new MyEntityReference(next)); 94 } 95 } 96 97 99 if ("lt".startsWith(prefix)) list.add(new MyEntityReference("lt")); 100 if ("gt".startsWith(prefix)) list.add(new MyEntityReference("gt")); 101 if ("apos".startsWith(prefix)) list.add(new MyEntityReference("apos")); 102 if ("quot".startsWith(prefix)) list.add(new MyEntityReference("quot")); 103 if ("amp".startsWith(prefix)) list.add(new MyEntityReference("amp")); 104 105 Collections.sort(list, new Comparator() { 106 public int compare(Object o1, Object o2) { 107 return ((MyEntityReference)o1).getNodeName().compareTo(((MyEntityReference)o2).getNodeName()); 108 } 109 public boolean equals(Object obj) { 110 return true; 111 } 112 }); 113 114 return java.util.Collections.enumeration (list); 115 } 116 117 125 public Enumeration queryAttributes(HintContext ctx) { 126 if (attrDecls == null) return org.openide.util.Enumerations.empty(); 127 128 Element el = null; 129 String currentAttrName = null; 130 if (ctx.getNodeType() == Node.ATTRIBUTE_NODE) { 132 currentAttrName = ctx.getNodeName(); 133 el = ((Attr)ctx).getOwnerElement(); 134 } else if (ctx.getNodeType() == Node.ELEMENT_NODE) { 135 el = (Element) ctx; 136 } 137 if (el == null) return org.openide.util.Enumerations.empty(); 138 139 NamedNodeMap existingAttributes = el.getAttributes(); 140 141 Set possibleAttributes = (Set) attrDecls.get(el.getTagName()); 142 if (possibleAttributes == null) return org.openide.util.Enumerations.empty(); 143 144 String prefix = ctx.getCurrentPrefix(); 145 146 LinkedList list = new LinkedList (); 147 Iterator it = possibleAttributes.iterator(); 148 while ( it.hasNext()) { 149 String next = (String ) it.next(); 150 if (next.startsWith(prefix)) { 151 if (existingAttributes.getNamedItem(next) == null || 152 next.equals(currentAttrName)) { 153 list.add (new MyAttr(next)); 154 } 155 } 156 } 157 158 return Collections.enumeration (list); 159 } 160 161 170 public Enumeration queryElements(HintContext ctx) { 171 if (elementDecls == null) return org.openide.util.Enumerations.empty();; 172 173 Node node = ((Node)ctx).getParentNode(); 174 Set elements = null; 175 176 if (node instanceof Element) { 177 Element el = (Element) node; 178 if (el == null) return org.openide.util.Enumerations.empty();; 179 180 Object model = null; 182 String prefs = System.getProperty("netbeans.xml.completion", "default"); if ("fast".equals(prefs)) { model = null; 185 } else if ("default".equals(prefs) || "accurate".equals(prefs)) { model = contentModels.get(el.getTagName()); 187 } else { 188 model = null; 189 } 190 if (model instanceof String ) { 191 model = ContentModel.parseContentModel((String )model); 192 contentModels.put(el.getTagName(), model); 193 } 194 if (model instanceof ContentModel) { 195 Enumeration en = ((ContentModel)model).whatCanFollow(new PreviousEnumeration(el, ctx)); 196 if (en == null) return org.openide.util.Enumerations.empty(); 197 String prefix = ctx.getCurrentPrefix(); 198 elements = new TreeSet(); 199 while (en.hasMoreElements()) { 200 String next = (String ) en.nextElement(); 201 if (next.startsWith(prefix)) { 202 elements.add(next); 203 } 204 } 205 } 206 if (elements == null) { 208 elements = (Set) elementDecls.get(el.getTagName()); 209 } 210 } else if (node instanceof Document) { 211 elements = elementDecls.keySet(); } else { 213 return org.openide.util.Enumerations.empty(); 214 } 215 216 if (elements == null) return org.openide.util.Enumerations.empty();; 217 String prefix = ctx.getCurrentPrefix(); 218 219 LinkedList list = new LinkedList (); 220 Iterator it = elements.iterator(); 221 while ( it.hasNext()) { 222 String next = (String ) it.next(); 223 if (next.startsWith(prefix)) { 224 boolean empty = emptyElements.contains(next); 225 list.add(new MyElement(next, empty)); 226 } 227 } 228 229 return Collections.enumeration (list); 230 } 231 232 236 public Enumeration queryNotations(String prefix) { 237 if (notations == null) return org.openide.util.Enumerations.empty();; 238 239 LinkedList list = new LinkedList (); 240 Iterator it = notations.iterator(); 241 while ( it.hasNext()) { 242 String next = (String ) it.next(); 243 if (next.startsWith(prefix)) { 244 list.add (new MyNotation(next)); 245 } 246 } 247 248 return Collections.enumeration (list); 249 } 250 251 260 public Enumeration queryValues(HintContext ctx) { 261 if (attrEnumerations.isEmpty()) return org.openide.util.Enumerations.empty(); 262 263 if (ctx.getNodeType() == Node.ATTRIBUTE_NODE) { 264 String attributeName = ctx.getNodeName(); 265 Element element = ((Attr)ctx).getOwnerElement(); 266 if (element == null) return org.openide.util.Enumerations.empty(); 267 268 String elementName = element.getNodeName(); 269 String key = elementName + " " + attributeName; 270 List values = (List) attrEnumerations.get(key); 271 if (values == null) return org.openide.util.Enumerations.empty(); 272 273 String prefix = ctx.getCurrentPrefix(); 274 LinkedList en = new LinkedList (); 275 Iterator it = values.iterator(); 276 while (it.hasNext()) { 277 String next = (String ) it.next(); 278 if (next.startsWith(prefix)) { 279 en.add(new MyText(next, next)); 280 } 281 } 282 return Collections.enumeration (en); 283 } 284 return org.openide.util.Enumerations.empty(); 285 } 286 287 public GrammarResult queryDefault(final HintContext ctx) { 289 290 Node node = ctx; 291 292 if (ctx.getNodeType() == Node.TEXT_NODE) { 293 node = ctx.getParentNode(); 294 if (node == null) return null; 295 } 296 297 if (node.getNodeType() == Node.ATTRIBUTE_NODE) { 298 Attr attr = (Attr) node; 299 Element element = attr.getOwnerElement(); 300 if (element == null) return null; 301 302 String elementName = element.getNodeName(); 303 String attributeName = attr.getNodeName(); 304 String key = elementName + " " + attributeName; String def = (String ) defaultAttributeValues.get(key); 306 if (def == null) return null; 307 return new MyText(def, def); 308 } 309 310 return null; 311 } 312 313 public boolean isAllowed(Enumeration en) { 315 return true; 316 } 317 318 320 public java.awt.Component getCustomizer(HintContext ctx) { 321 return null; 322 } 323 324 public boolean hasCustomizer(HintContext ctx) { 325 return false; 326 } 327 328 public org.openide.nodes.Node.Property[] getProperties(HintContext ctx) { 329 return null; 330 } 331 332 333 334 public String toString() { 335 return "DTD grammar"; 336 } 338 339 343 private static class PreviousEnumeration implements Enumeration { 344 345 private final Node parent; 346 private final Element lastElement; 347 private Node next; 348 private boolean eoeSeen = false; 349 350 PreviousEnumeration(Node parent, Node pointer) { 351 this.parent = parent; 352 Node last = pointer.getPreviousSibling(); 353 while (last != null) { 354 if (last.getNodeType() == Node.ELEMENT_NODE) break; 355 last = last.getPreviousSibling(); 356 } 357 lastElement = (Element) last; 358 359 361 if (last != null) { 362 fetchNext(parent.getFirstChild()); 363 } else { 364 next = null; 365 } 366 367 } 368 369 public boolean hasMoreElements() { 370 return next != null; 371 } 372 373 public Object nextElement() { 374 if (next == null) throw new NoSuchElementException(); 375 try { 376 return next.getNodeName(); 377 } finally { 378 fetchNext(next.getNextSibling()); 379 } 380 } 381 382 386 private void fetchNext(Node candidate) { 387 next = candidate; 388 if (eoeSeen) { 389 next = null; 390 } else { 391 while (next != null) { 392 if (next.getNodeType() == Node.ELEMENT_NODE) break; 393 next = next.getNextSibling(); 394 } 395 if (lastElement.equals(next)) eoeSeen = true; 397 } 398 } 399 } 400 401 403 404 private static abstract class AbstractResultNode extends AbstractNode implements GrammarResult { 405 406 public Icon getIcon(int kind) { 407 return null; 408 } 409 410 413 public String getDescription() { 414 return getNodeName() + " desc"; 415 } 416 417 421 public String getText() { 422 return getNodeName(); 423 } 424 425 428 public String getDisplayName() { 429 return null; 430 } 431 432 public boolean isEmptyElement() { 433 return false; 434 } 435 } 436 437 private static class MyEntityReference extends AbstractResultNode implements EntityReference { 438 439 private String name; 440 441 MyEntityReference(String name) { 442 this.name = name; 443 } 444 445 public short getNodeType() { 446 return Node.ENTITY_REFERENCE_NODE; 447 } 448 449 public String getNodeName() { 450 return name; 451 } 452 453 454 } 455 456 private static class MyElement extends AbstractResultNode implements Element { 457 458 private String name; 459 460 private boolean empty; 461 462 MyElement(String name, boolean empty) { 463 this.name = name; 464 this.empty = empty; 465 } 466 467 public short getNodeType() { 468 return Node.ELEMENT_NODE; 469 } 470 471 public String getNodeName() { 472 return name; 473 } 474 475 public String getTagName() { 476 return name; 477 } 478 479 public boolean isEmptyElement() { 480 return empty; 481 } 482 } 483 484 private static class MyAttr extends AbstractResultNode implements Attr { 485 486 private String name; 487 488 MyAttr(String name) { 489 this.name = name; 490 } 491 492 public short getNodeType() { 493 return Node.ATTRIBUTE_NODE; 494 } 495 496 public String getNodeName() { 497 return name; 498 } 499 500 public String getName() { 501 return name; 502 } 503 504 public String getValue() { 505 return null; } 507 508 509 } 510 511 private static class MyNotation extends AbstractResultNode implements Notation { 512 513 private String name; 514 515 MyNotation(String name) { 516 this.name = name; 517 } 518 519 public short getNodeType() { 520 return Node.NOTATION_NODE; 521 } 522 523 public String getNodeName() { 524 return name; 525 } 526 527 } 528 529 private static class MyText extends AbstractResultNode implements Text { 530 531 private final String data; 532 private final String displayName; 533 534 MyText(String data, String displayName) { 535 this.data = data; 536 this.displayName = displayName; 537 } 538 539 public short getNodeType() { 540 return Node.TEXT_NODE; 541 } 542 543 public String getNodeValue() { 544 return getData(); 545 } 546 547 public String getData() throws DOMException { 548 return data; 549 } 550 551 public int getLength() { 552 return data == null ? -1 : data.length(); 553 } 554 555 public String getDisplayName() { 556 return displayName; 557 } 558 } 559 560 } 561 | Popular Tags |