1 19 20 package org.netbeans.modules.enode; 21 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.HashMap ; 26 import java.util.HashSet ; 27 import java.util.LinkedList ; 28 import java.util.List ; 29 import java.util.Iterator ; 30 import java.util.ListIterator ; 31 import java.util.Map ; 32 import java.util.Set ; 33 34 import javax.swing.Action ; 35 import javax.swing.JComponent ; 36 import javax.swing.JSeparator ; 37 38 import org.openide.ErrorManager; 39 import org.openide.util.WeakListeners; 40 41 import org.netbeans.api.enode.*; 42 import org.netbeans.api.registry.*; 43 44 49 public class ExtensibleActionsImpl extends ExtensibleActions { 50 51 private static ErrorManager log = ErrorManager.getDefault().getInstance(ExtensibleActionsImpl.class.getName()); 52 private static boolean LOGGABLE = log.isLoggable(ErrorManager.INFORMATIONAL); 53 54 57 private String [] paths; 58 59 63 private Listener listener; 64 65 68 private Action [] actions; 69 70 73 private boolean listenersAttached = false; 74 75 81 private Set listenersAttachedTo = new HashSet (); 82 83 86 public ExtensibleActionsImpl(String [] paths) { 87 this.paths = paths; 88 } 89 90 95 public Action [] getActions() { 96 if (LOGGABLE) log.log("getActions() called on " + this); 97 if (actions != null) { 98 if (LOGGABLE) log.log("returning cached actions: "); 99 return actions; 100 } 101 102 List arr = new ArrayList (); 104 List location = new ArrayList (); 106 107 String cpaths[] = getCookiePaths(); 108 try { 109 for (int i = 0; i < paths.length; i++) { 110 String path = ExtensibleNode.E_NODE_ACTIONS + paths[i]; 111 scanContext(path, arr, location); 112 } 113 for (int i = 0; i < cpaths.length; i++) { 114 String path = ExtensibleNode.E_NODE_ACTIONS + cpaths[i]; 115 scanContext(path, arr, location); 116 } 117 if (LOGGABLE) log("arr after scanContext", arr); 118 List result = scanSubFolderContext(arr, location); 119 if (LOGGABLE) log("result after scanSubFolderContext", result); 120 Map m = new HashMap (); for (Iterator it = result.iterator(); it.hasNext();) { 122 Object obj = it.next(); 123 if (obj instanceof SubMenuAction) { 124 if (m.containsKey(obj)) { 125 it.remove(); 127 if (LOGGABLE) log.log("removed " + obj); 128 SubMenuAction removed = (SubMenuAction)obj; 130 SubMenuAction sma = (SubMenuAction)m.get(obj); 131 if (removed != sma) { if (LOGGABLE) log.log("adding all cache entries to " + sma); 135 sma.addAllCacheItems(removed.getCacheItries()); 136 } 137 } else { 138 m.put(obj, obj); 139 } 140 } 141 } 142 if (LOGGABLE) log("result after removing duplicates", result); 143 List rest = new ArrayList (arr); 144 if (LOGGABLE) log("rest", rest); 145 result.addAll(rest); 147 arr = result; 148 149 } catch (Exception ce) { 150 log.notify(ErrorManager.INFORMATIONAL, ce); } 152 for (int i = 0; i < arr.size(); i++) { 154 Object element = arr.get(i); 155 if (element instanceof JSeparator ) { 156 arr.set(i, null); 157 } 158 } 159 if (LOGGABLE) log("arr before returning", arr); 160 listenersAttached = true; actions = (Action [])arr.toArray(new Action [arr.size()]); 162 return actions; 163 } 164 165 168 private static void log(String name, Collection c) { 169 log.log("Dumping " + name); 170 for (Iterator it = c.iterator(); it.hasNext();) { 171 Object obj = it.next(); 172 if (obj != null) { 173 log.log(obj.toString()); 174 } else { 175 log.log("null"); 176 } 177 } 178 log.log("End of " + name); 179 } 180 181 184 private String subFoldersLocation() { 185 return ExtensibleNode.E_NODE_SUBMENUS; 186 } 187 188 191 private void scanContext(String path, List arr, List location) { 192 if (LOGGABLE) log.log("scanContext(" + path + ",arr) called on " + this); 193 boolean exists = true; 194 Context con = Context.getDefault().getSubcontext(path); 195 if (con == null) { 196 exists = false; 197 con = ExtensibleLookupImpl.findExistingContext(path); 198 } 199 if (!listenersAttached) { 200 ContextListener l1 = getContextListener(con); 201 con.addContextListener(l1); 202 listenersAttachedTo.add(con); 203 } 204 205 if (! exists) { 206 if (LOGGABLE) log.log("scanContext(" + path + ",arr) returning - context does not exist."); 207 return; 208 } 209 210 List names = con.getOrderedNames(); 211 Iterator it = names.iterator(); 212 while (it.hasNext()) { 213 String objName = (String )it.next(); 214 Object obj = con.getObject(objName, null); 215 String absName = con.getAbsoluteContextName()+"/"+objName; 216 if (absName.startsWith("/")) { 217 absName = absName.substring(1); 218 } 219 if (LOGGABLE) log.log("scanContext(...) checking " + obj + " with absName " + absName); 220 if (obj instanceof Action ) { 221 arr.add(obj); 222 location.add(absName); 223 if (LOGGABLE) log.log("scanContext(...) adding " + obj + " with name " + absName); 224 continue; 225 } 226 if (obj instanceof JSeparator ) { 229 arr.add(obj); 230 location.add(absName); 231 if (LOGGABLE) log.log("scanContext(...) adding " + obj + " with name " + absName); 232 continue; 233 } 234 if (obj instanceof JComponent ) { 236 Action a = new ComponentAction((JComponent )obj); 237 arr.add(a); 238 location.add(absName); 239 if (LOGGABLE) log.log("scanContext(...) adding " + a + " with name " + absName); 240 continue; 241 } 242 } 243 } 244 245 249 private List scanSubFolderContext(List objects, List location) { 250 String path = subFoldersLocation(); 251 if (LOGGABLE) log.log("scanSubFolderContext(...) with " + path + ") called on " + this); 252 List linkedList = new LinkedList (); 253 boolean exists = true; 254 Context con = Context.getDefault().getSubcontext(path); 255 if (con == null) { 256 exists = false; 257 con = ExtensibleLookupImpl.findExistingContext(path); 258 } 259 if (!listenersAttached) { 260 ContextListener l1 = getContextListener(con); 261 con.addContextListener(l1); 262 listenersAttachedTo.add(con); 263 } 264 265 if (! exists) { 266 if (LOGGABLE) log.log("scanSubFolderContext(...) returning empty list because " + path + " does not exist."); 267 return new ArrayList (); 268 } 269 270 Iterator locationIt = location.iterator(); 271 for (Iterator it = objects.iterator(); it.hasNext(); ) { 272 Object obj = it.next(); 273 String objLocation = (String )locationIt.next(); 274 if (LOGGABLE) log.log("scanSubFolderContext(...) checking " + obj + " with location " + objLocation); 275 if (objLocation == null) { 276 throw new IllegalStateException ("Did not find location for " + obj); 277 } 278 SubMenuCache.CacheEntry entry = SubMenuCache.getInstance().getCacheEntry(objLocation); 279 if (entry == null) { 280 if (LOGGABLE) log.log(obj + " with location " + objLocation + " was not found in cache"); 281 continue; 282 } 283 ActionCacheEntryPair pair = new ActionCacheEntryPair(); 284 if (entry.getParent().getParent() == null) { 285 pair.entry = entry; 286 if (obj instanceof Action ) { 287 pair.action = (Action )obj; 288 it.remove(); 290 locationIt.remove(); 291 } 292 if ((obj instanceof JComponent ) && (! (obj instanceof JSeparator ))) { 294 pair.action = new ComponentAction((JComponent )obj); 295 it.remove(); 297 locationIt.remove(); 298 } 299 if (obj instanceof JSeparator ) { 302 it.remove(); 305 locationIt.remove(); 306 } 307 } else { 308 SubMenuCache.CacheEntry origEntry = entry; 309 while (entry.getParent().getParent() != null) { 311 entry = entry.getParent(); 312 } 313 pair.entry = entry; 314 if (entry instanceof SubMenuCache.MenuEntry) { 315 SubMenuAction sma = new SubMenuAction((SubMenuCache.MenuEntry)entry); 316 pair.action = sma; 317 sma.addItemFromCache(origEntry); 318 it.remove(); 320 locationIt.remove(); 321 } else { 322 log.log(entry + " is not MenuEntry! adding null instead of " + obj); 323 } 324 } 325 insertPair(linkedList, pair); 326 } 327 ArrayList arr = new ArrayList (); 328 for (Iterator it = linkedList.iterator(); it.hasNext();) { 329 ActionCacheEntryPair acep = (ActionCacheEntryPair)it.next(); 330 arr.add(acep.action); 331 } 332 return arr; 333 } 334 335 338 private static void insertPair(List list, ActionCacheEntryPair pair) { 339 ActionCacheEntryPair existing = null; 340 ListIterator it = list.listIterator(); 341 while (it.hasNext()) { 342 existing = (ActionCacheEntryPair)it.next(); 343 if (! pair.entry.getParent().equals(existing.entry.getParent())) { 344 throw new IllegalStateException (pair.entry + " and " + existing.entry + " don't have the same parent"); 345 } 346 int pairIndex = pair.entry.getIndex(); 347 int existingIndex = existing.entry.getIndex(); 348 if (pairIndex < existingIndex) { 349 if (it.hasPrevious()) { 350 ActionCacheEntryPair previous = (ActionCacheEntryPair)it.previous(); 351 } 352 it.add(pair); 353 return; 354 } 355 } 356 it.add(pair); 358 } 359 360 364 private String [] getCookiePaths() { 365 if (LOGGABLE) log.log("getCookiePaths() called on " + this); 366 ArrayList names = new ArrayList (); 367 for (int i = 0; i < paths.length; i++) { 368 String path = ExtensibleNode.E_NODE_LOOKUP + paths[i]; 369 if (LOGGABLE) log.log("getCookiePaths() checking " + path); 370 try { 371 boolean exists = true; 372 Context con = Context.getDefault().getSubcontext(path); 373 if (con == null) { 374 con = ExtensibleLookupImpl.findExistingContext(path); 375 exists = false; 376 } 377 if (!listenersAttached) { 378 ContextListener l1 = getContextListener(con); 379 con.addContextListener(l1); 380 listenersAttachedTo.add(con); 381 } 382 if (exists) { 383 Collection objects = con.getBindingNames(); 384 if (LOGGABLE) { 385 log.log("getCookiePaths() adding names:"); 386 for (Iterator it = objects.iterator(); it.hasNext();) { 387 Object tmp = it.next(); 388 if (tmp != null) { 389 log.log( tmp.toString()); 390 } 391 } 392 } 393 names.addAll(objects); 394 } 395 } catch (Exception ce) { 396 log.notify(ErrorManager.INFORMATIONAL, ce); } 398 } 399 if (LOGGABLE) log.log("getCookiePaths() returning " + names.size() + " names."); 400 return (String [])names.toArray(new String [names.size()]); 401 } 402 403 public String toString() { 404 String res = "ExtensibleActionsImpl["; 405 if (paths != null) { 406 res += "path="; 407 for (int i = 0; i < paths.length; i++) { 408 res += paths[i] + ","; 409 } 410 } 411 if (actions != null) { 412 res += "actions="; 413 for (int i = 0; i < actions.length; i++) { 414 res += actions[i] + ","; 415 } 416 } 417 return res + "]"; 418 } 419 420 426 private ContextListener getContextListener(Object source) { 427 if (listener == null) { 428 listener = new Listener(); 429 } 430 if (LOGGABLE) log.log(this + " adding context listener to " + source); 431 return (ContextListener)WeakListeners.create(ContextListener.class, listener, source); 432 } 433 434 439 private class Listener implements ContextListener { 440 public void attributeChanged(AttributeEvent evt) { 441 if (LOGGABLE) log.log("attributeChanged("+evt+") called on listener from " + ExtensibleActionsImpl.this); 442 actions = null; 443 } 444 445 public void bindingChanged(BindingEvent evt) { 446 if (LOGGABLE) log.log("bindingChanged("+evt+") called on listener from " + ExtensibleActionsImpl.this); 447 actions = null; 448 } 449 450 public void subcontextChanged(SubcontextEvent evt) { 451 if (LOGGABLE) log.log("subcontextChanged("+evt+") called on listener from " + ExtensibleActionsImpl.this); 452 actions = null; 453 } 454 } 455 456 private static class ActionCacheEntryPair { 457 public Action action; 458 public SubMenuCache.CacheEntry entry; 459 } 460 } 461 | Popular Tags |