1 19 20 package org.netbeans.modules.java.ui.nodes.elements; 21 22 import java.util.*; 23 24 import org.openide.nodes.Children; 25 import org.openide.nodes.Node; 26 import org.openide.nodes.FilterNode; 27 import org.openide.cookies.FilterCookie; 28 import org.openide.src.ElementProperties; 29 import org.openide.ErrorManager; 30 import org.netbeans.jmi.javamodel.*; 31 import org.netbeans.modules.java.ui.nodes.SourceNodeFactory; 32 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 33 import org.netbeans.api.mdr.events.MDRChangeListener; 34 import org.netbeans.api.mdr.events.MDRChangeEvent; 35 import org.netbeans.api.mdr.events.AttributeEvent; 36 import org.netbeans.api.mdr.events.MDRChangeSource; 37 38 import javax.jmi.reflect.JmiException; 39 import javax.jmi.reflect.InvalidObjectException; 40 41 44 public class ClassChildren extends Children.Keys implements FilterCookie, ChildrenProvider.KeyHandler { 45 46 47 private static int PPP_MASK = SourceElementFilter.PUBLIC + SourceElementFilter.PRIVATE + SourceElementFilter.PROTECTED; 48 51 protected static HashMap propToFilter; 52 53 54 private static Comparator comparator = new Comparator() { 55 public int compare(Object o1, Object o2) { 56 if (o1 instanceof NamedElement) 57 if (o2 instanceof NamedElement) { 58 String o1Name = getName((NamedElement) o1); 59 String o2Name = getName((NamedElement) o2); 60 if (o1Name==null || o2Name==null) return 1; 61 return o1Name.compareToIgnoreCase(o2Name); 62 } else 63 return -1; 64 else 65 if (o2 instanceof NamedElement) 66 return 1; 67 else 68 return 0; 69 } 70 71 private String getName(NamedElement el) { 72 String name; 73 if (el instanceof Constructor) { 74 name = ((Constructor) el).getDeclaringClass().getName(); 75 } else if (el instanceof Initializer) { 76 name = ""; } else { 78 name = el.getName(); 79 } 80 return name; 81 } 82 }; 83 84 static { 85 propToFilter = new HashMap (); 86 propToFilter.put (ElementProperties.PROP_CLASSES, new Integer (ClassElementFilter.CLASS | ClassElementFilter.INTERFACE)); 87 propToFilter.put (ElementProperties.PROP_METHODS, new Integer (ClassElementFilter.METHOD)); 88 propToFilter.put (ElementProperties.PROP_FIELDS, new Integer (ClassElementFilter.FIELD)); 89 propToFilter.put (ElementProperties.PROP_CONSTRUCTORS, new Integer (ClassElementFilter.CONSTRUCTOR)); 90 propToFilter.put (ElementProperties.PROP_INITIALIZERS, new Integer (ClassElementFilter.CONSTRUCTOR)); 91 } 92 93 94 protected ClassDefinition element; 95 96 protected ClassElementFilter filter; 97 98 private SourceNodeFactory factory; 99 101 private JMIElementListener wPropL; 102 103 private boolean nodesInited = false; 104 private final ChildrenProvider chprovider = new ChildrenProvider(this); 105 106 107 109 114 public ClassChildren(SourceNodeFactory factory, ClassDefinition element) { 115 if (factory == null) throw new NullPointerException ("factory"); if (element == null) throw new NullPointerException ("element"); this.element = element; 118 this.factory = factory; 119 this.filter = null; 120 } 121 122 protected SourceNodeFactory getFactory() { 123 return this.factory; 124 } 125 126 127 128 131 public Class getFilterClass () { 132 return ClassElementFilter.class; 133 } 134 135 137 public Object getFilter () { 138 return filter; 139 } 140 141 144 public void setFilter (final Object filter) { 145 if (!(filter instanceof ClassElementFilter)) 146 throw new IllegalArgumentException (); 147 148 this.filter = (ClassElementFilter)filter; 149 if (nodesInited) 151 refreshAllKeys (); 152 } 153 154 155 157 160 protected void addNotify () { 161 super.addNotify(); 162 if (wPropL == null) { 164 wPropL = new JMIElementListener(this); 165 } 166 refreshAllKeys (); 167 ((MDRChangeSource) element).addListener(wPropL); 168 nodesInited = true; 169 } 170 171 protected void removeNotify () { 172 chprovider.clear(); 173 nodesInited = false; 174 super.removeNotify(); 175 } 176 177 protected final void hookNodeName(Element el) { 178 if (el instanceof MDRChangeSource) { 179 ((MDRChangeSource) el).addListener(wPropL); 180 } 181 } 182 183 186 protected final Node[] createNodes(Object key) { 187 Node[] nodes; 188 if (key instanceof Node) { 189 nodes = new Node[] {new FilterNode((Node) key)}; 190 } else if (key instanceof Node[]) { 191 Node[] ns = (Node[]) key; 192 nodes = new Node[ns.length]; 193 for (int i = 0; i < ns.length; i++) { 194 Node orig = ns[i]; 195 nodes[i] = orig == null? orig: new FilterNode(orig); 196 } 197 } else { 198 nodes = new Node[] {factory.createErrorNode()}; 199 ErrorManager.getDefault().notify( 200 ErrorManager.WARNING, 201 new IllegalStateException ("key: " + key) ); 203 } 204 return nodes; 205 } 206 207 protected Node[] createNodesImpl(Object key) throws JmiException { 208 Node n; 209 if (key instanceof Method) { 210 Method m = (Method) key; 211 hookNodeName(m); 212 n = factory.createMethodNode(m); 213 } else if (key instanceof Field) { 214 Field f = (Field) key; 215 hookNodeName(f); 216 n = factory.createFieldNode(f); 217 } else if (key instanceof Constructor) { 218 n = factory.createConstructorNode((Constructor) key); 220 } else if (key instanceof JavaEnum) { 221 JavaEnum en = (JavaEnum) key; 222 hookNodeName(en); 223 n = factory.createEnumNode(en); 224 } else if (key instanceof AnnotationType) { 225 AnnotationType at = (AnnotationType) key; 226 hookNodeName(at); 227 n = factory.createAnnotationTypeNode(at); 228 } else if (key instanceof JavaClass) { 229 JavaClass jc = (JavaClass) key; 230 hookNodeName(jc); 231 n = factory.createClassNode(jc); 232 } else if (key instanceof Initializer) { 233 n = factory.createInitializerNode((Initializer) key); 235 } else { 236 n = factory.createErrorNode(); 238 } 239 return new Node[] {n}; 240 } 241 242 public final List collectKeys() { 243 List keys = new LinkedList(); 244 int[] order = getOrder (); 245 try { 246 JavaMetamodel.getDefaultRepository().beginTrans(false); 247 try { 248 if (!element.isValid()) { 249 return keys; 250 } 251 List features = element.getFeatures(); 252 253 List members = new ArrayList(features.size()); 254 filterModifiers(features, members); 255 256 for (int i = 0; i < order.length; i++) { 257 List keysOfType = getKeysOfType(members, order[i]); 258 if ((this.filter == null) || this.filter.isSorted ()) { 259 Collections.sort(keysOfType, comparator); 260 } 261 keys.addAll(keysOfType); 262 } 263 } finally { 264 JavaMetamodel.getDefaultRepository().endTrans(); 265 } 266 } catch (InvalidObjectException ex) { 267 keys = Collections.EMPTY_LIST; 269 } catch (JmiException ex) { 270 ErrorManager.getDefault().notify(ErrorManager.WARNING, ex); 271 } 272 return keys; 273 } 274 275 public Node[] prepareNodes(Object key) { 276 return createNodesImpl(key); 277 } 278 279 public void presentKeys(List keys, List nodes) { 280 JMIElementListener l = wPropL; 281 if (l != null) 282 l.updateElements(keys); 283 setKeys(nodes); 284 } 285 286 public Node[] getNodes(boolean optimalResult) { 287 if (!optimalResult) { 288 return getNodes(); 289 } 290 chprovider.waitFinished(); 291 return getNodes(); 292 } 293 294 public Node findChild(String name) { 295 Node n = super.findChild(name); 296 if (n == null) { 297 chprovider.waitFinished(); 298 n = super.findChild(name); 299 } 300 return n; 301 } 302 303 304 305 308 protected void refreshAllKeys() { 309 refreshKeys(ClassElementFilter.ALL); 310 } 311 312 314 protected final void refreshKeys(int filter) { 315 if (!doRefresh(filter)) return; 316 chprovider.recomputeChildren(); 317 } 318 319 private boolean doRefresh(int filter) { 320 int[] order = getOrder(); 321 for (int i = order.length - 1; i >= 0 ; i--) { 322 if ((order[i] & filter) != 0) { 323 return true; 324 } 325 } 326 return false; 327 } 328 329 331 protected List getKeysOfType(Collection elements, final int elementType) { 332 List keys = new LinkedList(); 333 if ((elementType & ClassElementFilter.EXTENDS) != 0) { 334 keys.add(element.getSuperClass()); 335 } 336 if ((elementType & ClassElementFilter.IMPLEMENTS) != 0) { 337 keys.addAll(element.getInterfaces()); 338 } 339 340 Iterator it = elements.iterator(); 341 while (it.hasNext()) { 342 Object member = it.next(); 343 if ((elementType & ClassElementFilter.FIELD) != 0 && member instanceof Field && !(member instanceof EnumConstant)) { 344 keys.add(member); 345 } else if ((elementType & ClassElementFilter.CONSTRUCTOR) != 0 && 346 (member instanceof Constructor || member instanceof Initializer)) { 347 keys.add(member); 348 } else if ((elementType & ClassElementFilter.METHOD) != 0 && member instanceof Method) { 349 keys.add(member); 350 } 351 if (member instanceof JavaClass) { 352 boolean isInterface = ((JavaClass) member).isInterface(); 353 if ((elementType & ClassElementFilter.CLASS) != 0 && !isInterface) { 354 keys.add(member); 355 } else if ((elementType & ClassElementFilter.INTERFACE) != 0 && isInterface) { 356 keys.add(member); 357 } 358 } 359 } 360 361 return keys; 362 } 363 364 366 protected int[] getOrder () { 367 return (filter == null || (filter.getOrder() == null)) 368 ? ClassElementFilter.DEFAULT_ORDER : filter.getOrder(); 369 } 370 371 373 private int getModifierFilter () { 374 if (filter == null) return ClassElementFilter.ALL_MODIFIERS; 375 return filter.getModifiers (); 376 } 377 378 380 private void filterModifiers(Collection elements, Collection keys) { 381 int ff = getModifierFilter(); 382 for (Iterator it = elements.iterator(); it.hasNext();) { 383 ClassMember element = (ClassMember) it.next(); 384 int f = element.getModifiers(); 385 if ((f & PPP_MASK) == 0) f += ClassElementFilter.PACKAGE; 386 if ((f & ff) != 0) keys.add(element); 387 388 } 389 } 390 391 393 395 private static final class JMIElementListener extends java.lang.ref.WeakReference implements Runnable , MDRChangeListener { 396 Collection elements; 397 MDRChangeSource celem; 398 399 JMIElementListener(ClassChildren cc) { 400 super(cc, org.openide.util.Utilities.activeReferenceQueue()); 401 celem = (MDRChangeSource) cc.element; 402 } 403 404 ClassChildren getClassChildren() { 405 Object o = get(); 406 return (ClassChildren) o; 407 } 408 409 410 public void change(MDRChangeEvent e) { 411 int filter; 412 final Object src = e.getSource(); 413 414 if ((src instanceof Element) && !((Element) src).isValid()) { 415 return; 416 } 417 418 ClassChildren cc = getClassChildren(); 419 if (cc == null || !(e instanceof AttributeEvent)) 420 return; 421 422 AttributeEvent evt = (AttributeEvent) e; 423 String propName = evt.getAttributeName(); 424 425 438 if (src != cc.element) { 439 if (src instanceof Element && 440 (propName == null || ElementProperties.PROP_NAME == propName)) { 441 filter = chooseFilter((Element) src); 442 } else 444 return; 445 } else if ("contents".equals(propName)) { Element cm = (Element) evt.getOldElement(); 447 cm = (cm == null)? (Element) evt.getNewElement(): cm; 448 filter = chooseFilter(cm); 449 } else if ("constants".equals(propName)) { filter = EnumFilter.CONSTANTS; 452 } else { 453 return; 454 } 459 if (cc.nodesInited) { 460 cc.refreshKeys (filter); 461 } 462 } 463 464 int chooseFilter(Element src) { 465 int filter; 466 if (src instanceof Method) 467 filter = ClassElementFilter.METHOD; 468 else if ((src instanceof Constructor) || (src instanceof Initializer)) 469 filter = ClassElementFilter.CONSTRUCTOR; 470 else if (src instanceof Field) 471 filter = ClassElementFilter.FIELD; 472 else if (src instanceof EnumConstant) 473 filter = EnumFilter.CONSTANTS; 474 else if (src instanceof Attribute) 475 filter = AnnotationTypeFilter.MEMBER; 476 else 477 filter = ClassElementFilter.CLASS | ClassElementFilter.INTERFACE | 478 EnumFilter.ENUM | AnnotationTypeFilter.ANNOTATION_TYPE; 479 return filter; 480 } 481 482 void updateElements(Collection c) { 484 Collection old = this.elements; 485 if (old != null) { 486 old.removeAll(c); 487 removeListeners(old); 488 } 489 this.elements = c; 490 } 491 492 public void run() { 493 celem.removeListener(this); 495 removeListeners(this.elements); 496 } 497 498 private void removeListeners(Collection c) { 499 for (Iterator it = c.iterator(); it.hasNext(); ) { 500 Object o = it.next(); 501 if (!(o instanceof MDRChangeSource)) 502 continue; 503 MDRChangeSource el = (MDRChangeSource) o; 504 el.removeListener(this); 505 } 506 } 507 } 509 } 510 | Popular Tags |