1 19 20 package org.netbeans.modules.java.ui.nodes.elements; 21 22 import java.util.*; 23 import java.util.List ; 24 import java.lang.ref.WeakReference ; 25 26 import org.openide.nodes.Children; 27 import org.openide.nodes.Node; 28 import org.openide.nodes.FilterNode; 29 import org.openide.cookies.FilterCookie; 30 import org.openide.util.Utilities; 31 import org.openide.ErrorManager; 32 import org.openide.loaders.DataObject; 33 import org.netbeans.jmi.javamodel.*; 34 import org.netbeans.modules.java.ui.nodes.SourceNodeFactory; 35 import org.netbeans.modules.java.ui.nodes.JavaSourceNodeFactory; 36 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 37 import org.netbeans.api.mdr.events.*; 38 39 import javax.jmi.reflect.JmiException; 40 import javax.jmi.reflect.InvalidObjectException; 41 42 58 public class SourceChildren extends Children.Keys implements FilterCookie, ChildrenProvider.KeyHandler { 59 60 61 static final Object NOT_KEY = new Object (); 62 63 static final Object ERROR_KEY = new Object (); 64 65 private static int PPP_MASK = SourceElementFilter.PUBLIC + 66 SourceElementFilter.PRIVATE + 67 SourceElementFilter.PROTECTED; 68 69 70 protected Resource element; 71 73 protected SourceElementFilter filter; 74 75 protected SourceNodeFactory factory; 76 77 private JMIListener wElementL; 78 79 private boolean nodesInited = false; 80 81 private final ChildrenProvider chprovider = new ChildrenProvider(this); 82 83 private final ClassesListener CLS_LISTENER = new ClassesListener(this); 84 85 89 private DataObject resourceHolder; 90 91 93 95 public SourceChildren() { 96 this (JavaSourceNodeFactory.getDefault(), null); 97 } 98 99 102 public SourceChildren(Resource resource) { 103 this(JavaSourceNodeFactory.getDefault(), resource); 104 } 105 106 109 public SourceChildren(SourceNodeFactory factory) { 110 this(factory, null); 111 } 112 113 117 public SourceChildren(SourceNodeFactory factory, Resource resource) { 118 this.element = resource; 119 this.factory = factory; 120 this.filter = new SourceElementFilter(); 121 this.resourceHolder = resource != null? 122 JavaMetamodel.getManager().getDataObject(resource): null; 123 } 124 125 126 128 131 public Class getFilterClass() { 132 return SourceElementFilter.class; 133 } 134 135 137 public Object getFilter() { 138 return filter; 139 } 140 141 144 public void setFilter(Object filter) { 145 if (!(filter instanceof SourceElementFilter)) 146 throw new IllegalArgumentException (); 147 148 this.filter = (SourceElementFilter) filter; 149 if (nodesInited) 151 refreshAllKeys(); 152 } 153 154 protected Resource createResource() { 155 return null; 156 } 157 158 160 protected void addNotify () { 161 setKeys( Collections.singletonList(NOT_KEY)); 162 ChildrenProvider.RP.post(new Runnable () { 163 public void run() { 164 final Resource element; 165 if (SourceChildren.this.element == null) { 166 element = SourceChildren.this.createResource(); 167 } else { 168 element = null; 169 } 170 setElementImpl(element); 171 if (element != null) { 172 if (wElementL == null) { 174 wElementL = new JMIListener(SourceChildren.this, (MDRChangeSource) element); 175 } 176 ((MDRChangeSource) element).addListener(wElementL); 177 } 178 refreshAllKeys(); 179 nodesInited = true; 180 } 181 }); 182 } 183 184 protected void removeNotify () { 185 ChildrenProvider.RP.post(new Runnable () { 186 public void run() { 187 final Resource element = SourceChildren.this.element; 188 if (element != null) { 189 ((MDRChangeSource) element).removeListener(wElementL); 190 } 191 CLS_LISTENER.updateClasses(Collections.EMPTY_LIST); 192 chprovider.clear(); 193 nodesInited = false; 194 } 195 }); 196 } 197 198 protected Node[] createNodes(Object key) { 199 Node[] nodes; 200 if (NOT_KEY.equals(key)) { 201 nodes = new Node[] {factory.createWaitNode()}; 202 } else if (key instanceof Node) { 203 nodes = new Node[] {new FilterNode((Node) key)}; 204 } else if (key instanceof Node[]) { 205 Node[] ns = (Node[]) key; 206 nodes = new Node[ns.length]; 207 for (int i = 0; i < ns.length; i++) { 208 Node orig = ns[i]; 209 nodes[i] = orig == null? orig: new FilterNode(orig); 210 } 211 } else if (ERROR_KEY.equals(key)) { 212 nodes = new Node[] {factory.createWaitNode()}; 213 } else { 214 nodes = new Node[] {factory.createErrorNode()}; 216 ErrorManager.getDefault().notify( 217 ErrorManager.WARNING, 218 new IllegalStateException ("key: " + key) ); 220 } 221 return nodes; 222 } 223 224 private Node[] createNodesImpl(Object key) throws JmiException { 225 Node n; 227 if (key instanceof JavaEnum) { 228 n = factory.createEnumNode((JavaEnum) key); 229 } else if (key instanceof AnnotationType) { 230 n = factory.createAnnotationTypeNode((AnnotationType) key); 231 } else if (key instanceof JavaClass) { 232 n = factory.createClassNode((JavaClass) key); 233 } else if (NOT_KEY.equals(key)) { 234 n = factory.createWaitNode(); 235 } else { 236 n = factory.createErrorNode(); 238 } 239 240 return new Node[] {n}; 241 } 242 243 public Node[] getNodes(boolean optimalResult) { 244 if (!optimalResult || element == null) { 245 return getNodes(); 246 } 247 chprovider.waitFinished(); 248 return getNodes(); 249 } 250 251 public Node findChild(String name) { 252 Node n = super.findChild(name); 253 if (n == null) { 254 chprovider.waitFinished(); 255 n = super.findChild(name); 256 } 257 return n; 258 } 259 260 262 265 public Resource getElement() { 266 return element; 267 } 268 269 272 public void setElement(final Resource element) { 273 ChildrenProvider.RP.post(new Runnable () { 274 public void run() { 275 setElementImpl(element); 276 } 277 }); 278 } 279 280 private void setElementImpl(final Resource element) { 281 if (this.element != null) { 282 ((MDRChangeSource) this.element).removeListener(wElementL); 283 } 284 this.element = element; 285 CLS_LISTENER.updateClasses(Collections.EMPTY_LIST); 286 if (element != null) { 287 if (this.resourceHolder == null) { 288 this.resourceHolder = JavaMetamodel.getManager().getDataObject(element); 289 } 290 if (wElementL == null) { 291 wElementL = new JMIListener(this, (MDRChangeSource) element); 292 } else { 293 wElementL.source = (MDRChangeSource) element; 294 } 295 ((MDRChangeSource) element).addListener(wElementL); 296 } 297 if (nodesInited) { 299 refreshAllKeys(); 300 } 301 } 302 303 305 306 310 private void refreshAllKeys () { 311 List keys; 312 assert ChildrenProvider.RP.isRequestProcessorThread(); 313 if (element == null) { 314 keys = Collections.singletonList(ERROR_KEY); 315 setKeys(keys); 316 } else { 317 if (!nodesInited) { 318 keys = Collections.singletonList(NOT_KEY); 319 setKeys(keys); 320 } 321 chprovider.recomputeChildren(); 322 } 323 } 324 325 private List collectKeysImpl() { 326 Resource element = this.element; 327 if (element == null) { 328 return Collections.EMPTY_LIST; 329 } 330 int[] order = (filter == null || (filter.getOrder() == null)) 331 ? SourceElementFilter.DEFAULT_ORDER : filter.getOrder(); 332 final List keys = new LinkedList(); 333 try { 334 JavaMetamodel.getDefaultRepository().beginTrans(false); 335 try { 336 if (!element.isValid()) { 337 keys.add(ERROR_KEY); 338 return keys; 339 } 340 for (int i = 0; i < order.length; i++) 342 addKeysOfType(element, keys, order[i]); 343 } finally { 344 JavaMetamodel.getDefaultRepository().endTrans(); 345 } 346 } catch (InvalidObjectException ex) { 347 keys.clear(); 349 keys.add(ERROR_KEY); 350 } catch (JmiException ex) { 351 ErrorManager.getDefault().notify(ErrorManager.WARNING, ex); 352 } 353 354 return keys; 355 } 356 357 360 private void addKeysOfType(Resource element, Collection keys, final int elementType) { 361 if (elementType == SourceElementFilter.IMPORT) { 362 return; 365 } else { 366 List cls; 367 if ((filter != null) && filter.isAllClasses()) { 368 cls = SourceEditSupport.getAllClasses(element); 369 CLS_LISTENER.updateClasses(cls); 370 } else { 371 cls = element.getClassifiers(); 372 } 373 for (Iterator it = cls.iterator(); it.hasNext(); ) { 374 JavaClass classElement = (JavaClass) it.next(); 375 int modifiers = classElement.getModifiers(); 376 if ((modifiers & PPP_MASK) == 0) modifiers += SourceElementFilter.PACKAGE; 377 if ((filter.getModifiers () & modifiers) == 0) continue; 378 if (classElement instanceof JavaEnum) { 379 if ((elementType & SourceElementFilter.ENUM) != 0) keys.add(classElement); 380 } else if (classElement.isInterface()) { 381 if ((elementType & SourceElementFilter.INTERFACE) != 0) keys.add(classElement); 382 } else 383 if ((elementType & SourceElementFilter.CLASS) != 0) keys.add(classElement); 384 } 385 } 386 } 387 388 public List collectKeys() { 389 return this.collectKeysImpl(); 390 } 391 392 public Node[] prepareNodes(Object key) { 393 return this.createNodesImpl(key); 394 } 395 396 public void presentKeys(List keys, List nodes) { 397 setKeys(nodes); 398 } 399 400 402 403 private static final class JMIListener extends WeakReference implements MDRChangeListener, Runnable { 404 405 private MDRChangeSource source; 406 407 public JMIListener(SourceChildren referent, MDRChangeSource source) { 408 super(referent, Utilities.activeReferenceQueue()); 409 this.source = source; 410 } 411 412 public void change(final MDRChangeEvent e) { 413 final SourceChildren sc = (SourceChildren) get(); 414 if (sc == null) return; 415 ChildrenProvider.RP.post(new Runnable () { 416 public void run() { 417 processChange(e, sc); 418 } 419 }); 420 } 421 422 private void processChange(MDRChangeEvent e, SourceChildren sc) { 423 if (e instanceof AttributeEvent) { 424 if (sc.element == null || !sc.element.isValid()) return; 425 426 final AttributeEvent ae = (AttributeEvent) e; 427 if ("classifiers".equals(ae.getAttributeName()) && sc.nodesInited) { sc.refreshAllKeys(); 429 } 430 } else if (e instanceof InstanceEvent) { 431 InstanceEvent ie = (InstanceEvent) e; 433 Object o = ie.getInstance(); 434 if (o == sc.element && !sc.element.isValid()) { 435 DataObject dobj = sc.resourceHolder; 436 if (dobj != null && dobj.isValid()) { 437 Resource newRes = JavaMetamodel.getManager().getResource(dobj.getPrimaryFile()); 438 sc.setElement(newRes); 439 } else { 440 sc.setElement(null); 441 } 442 } 443 } 444 } 445 446 public void run() { 447 source.removeListener(this); 448 } 449 450 } 451 452 458 private static final class ClassesListener implements MDRChangeListener { 459 460 private SourceChildren sc; 461 462 463 private List classes; 464 465 public ClassesListener(SourceChildren sc) { 466 this.sc = sc; 467 this.classes = Collections.EMPTY_LIST; 468 } 469 470 474 public void updateClasses(List classes) { 475 List toAdd = new ArrayList(classes); 476 toAdd.removeAll(this.classes); 477 this.classes.removeAll(classes); 478 addListeners(toAdd); 479 removeListeners(this.classes); 480 this.classes = new ArrayList(classes); 481 } 482 483 public void change(final MDRChangeEvent e) { 484 ChildrenProvider.RP.post(new Runnable () { 485 public void run() { 486 processChange(e, sc); 487 } 488 }); 489 } 490 491 private void processChange(MDRChangeEvent e, SourceChildren sc) { 492 if (e instanceof AttributeEvent) { 493 if (sc.element == null) return; 494 495 final AttributeEvent ae = (AttributeEvent) e; 496 if ("contents".equals(ae.getAttributeName()) && sc.nodesInited) { Element cm = (Element) ae.getOldElement(); 498 cm = (cm == null)? (Element) ae.getNewElement(): cm; 499 if (cm != null && cm instanceof JavaClass) { 500 sc.refreshAllKeys(); 502 } 503 } 504 } 505 } 506 507 private void addListeners(List c) { 508 for (Iterator it = c.iterator(); it.hasNext(); ) { 509 Object o = it.next(); 510 if (!(o instanceof MDRChangeSource)) 511 continue; 512 MDRChangeSource el = (MDRChangeSource) o; 513 el.addListener(this); 514 } 515 } 516 517 private void removeListeners(List c) { 518 for (Iterator it = c.iterator(); it.hasNext(); ) { 519 Object o = it.next(); 520 if (!(o instanceof MDRChangeSource)) 521 continue; 522 MDRChangeSource el = (MDRChangeSource) o; 523 el.removeListener(this); 524 } 525 } 526 } 527 528 } 529 | Popular Tags |