1 11 package org.eclipse.jdt.internal.ui.workingsets; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collections ; 16 import java.util.HashMap ; 17 import java.util.IdentityHashMap ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 import org.eclipse.core.runtime.Assert; 23 import org.eclipse.core.runtime.IAdaptable; 24 import org.eclipse.core.runtime.ListenerList; 25 26 import org.eclipse.core.resources.IProject; 27 import org.eclipse.core.resources.IResource; 28 29 import org.eclipse.jface.util.IPropertyChangeListener; 30 import org.eclipse.jface.util.PropertyChangeEvent; 31 import org.eclipse.jface.viewers.IElementComparer; 32 33 import org.eclipse.ui.ILocalWorkingSetManager; 34 import org.eclipse.ui.IMemento; 35 import org.eclipse.ui.IWorkingSet; 36 import org.eclipse.ui.IWorkingSetManager; 37 import org.eclipse.ui.IWorkingSetUpdater; 38 import org.eclipse.ui.PlatformUI; 39 40 import org.eclipse.jdt.core.IJavaElement; 41 import org.eclipse.jdt.core.IJavaProject; 42 43 public class WorkingSetModel { 44 45 public static final String CHANGE_WORKING_SET_MODEL_CONTENT= "workingSetModelChanged"; 47 public static final IElementComparer COMPARER= new WorkingSetComparar(); 48 49 private static final String TAG_LOCAL_WORKING_SET_MANAGER= "localWorkingSetManager"; private static final String TAG_ACTIVE_WORKING_SET= "activeWorkingSet"; private static final String TAG_WORKING_SET_NAME= "workingSetName"; private static final String TAG_CONFIGURED= "configured"; 54 private ILocalWorkingSetManager fLocalWorkingSetManager; 55 private List fActiveWorkingSets; 56 private ListenerList fListeners; 57 private IPropertyChangeListener fWorkingSetManagerListener; 58 private OthersWorkingSetUpdater fOthersWorkingSetUpdater; 59 60 private ElementMapper fElementMapper= new ElementMapper(); 61 62 private boolean fConfigured; 63 64 private static class WorkingSetComparar implements IElementComparer { 65 public boolean equals(Object o1, Object o2) { 66 IWorkingSet w1= o1 instanceof IWorkingSet ? (IWorkingSet)o1 : null; 67 IWorkingSet w2= o2 instanceof IWorkingSet ? (IWorkingSet)o2 : null; 68 if (w1 == null || w2 == null) 69 return o1.equals(o2); 70 return w1 == w2; 71 } 72 public int hashCode(Object element) { 73 if (element instanceof IWorkingSet) 74 return System.identityHashCode(element); 75 return element.hashCode(); 76 } 77 } 78 79 private static class ElementMapper { 80 private Map fElementToWorkingSet= new HashMap (); 81 private Map fWorkingSetToElement= new IdentityHashMap (); 82 83 private Map fResourceToWorkingSet= new HashMap (); 84 private List fNonProjectTopLevelElements= new ArrayList (); 85 86 public void clear() { 87 fElementToWorkingSet.clear(); 88 fWorkingSetToElement.clear(); 89 fResourceToWorkingSet.clear(); 90 fNonProjectTopLevelElements.clear(); 91 } 92 public void rebuild(IWorkingSet[] workingSets) { 93 clear(); 94 for (int i= 0; i < workingSets.length; i++) { 95 put(workingSets[i]); 96 } 97 } 98 public IAdaptable[] remove(IWorkingSet ws) { 99 IAdaptable[] elements= (IAdaptable[])fWorkingSetToElement.remove(ws); 100 if (elements != null) { 101 for (int i= 0; i < elements.length; i++) { 102 removeElement(elements[i], ws); 103 } 104 } 105 return elements; 106 } 107 public IAdaptable[] refresh(IWorkingSet ws) { 108 IAdaptable[] oldElements= (IAdaptable[])fWorkingSetToElement.get(ws); 109 if (oldElements == null) 110 return null; 111 IAdaptable[] newElements= ws.getElements(); 112 List toRemove= new ArrayList (Arrays.asList(oldElements)); 113 List toAdd= new ArrayList (Arrays.asList(newElements)); 114 computeDelta(toRemove, toAdd, oldElements, newElements); 115 for (Iterator iter= toAdd.iterator(); iter.hasNext();) { 116 addElement((IAdaptable)iter.next(), ws); 117 } 118 for (Iterator iter= toRemove.iterator(); iter.hasNext();) { 119 removeElement((IAdaptable)iter.next(), ws); 120 } 121 if (toRemove.size() > 0 || toAdd.size() > 0) 122 fWorkingSetToElement.put(ws, newElements); 123 return oldElements; 124 } 125 private void computeDelta(List toRemove, List toAdd, IAdaptable[] oldElements, IAdaptable[] newElements) { 126 for (int i= 0; i < oldElements.length; i++) { 127 toAdd.remove(oldElements[i]); 128 } 129 for (int i= 0; i < newElements.length; i++) { 130 toRemove.remove(newElements[i]); 131 } 132 133 } 134 public IWorkingSet getFirstWorkingSet(Object element) { 135 return (IWorkingSet)getFirstElement(fElementToWorkingSet, element); 136 } 137 public List getAllWorkingSets(Object element) { 138 List allElements= getAllElements(fElementToWorkingSet, element); 139 if (allElements.isEmpty() && element instanceof IJavaElement) { 140 allElements= getAllElements(fElementToWorkingSet, ((IJavaElement) element).getResource()); 142 } 143 return allElements; 144 } 145 public IWorkingSet getFirstWorkingSetForResource(IResource resource) { 146 return (IWorkingSet)getFirstElement(fResourceToWorkingSet, resource); 147 } 148 public List getAllWorkingSetsForResource(IResource resource) { 149 return getAllElements(fResourceToWorkingSet, resource); 150 } 151 public List getNonProjectTopLevelElements() { 152 return fNonProjectTopLevelElements; 153 } 154 private void put(IWorkingSet ws) { 155 if (fWorkingSetToElement.containsKey(ws)) 156 return; 157 IAdaptable[] elements= ws.getElements(); 158 fWorkingSetToElement.put(ws, elements); 159 for (int i= 0; i < elements.length; i++) { 160 IAdaptable element= elements[i]; 161 addElement(element, ws); 162 if (!(element instanceof IProject) && !(element instanceof IJavaProject)) { 163 fNonProjectTopLevelElements.add(element); 164 } 165 } 166 } 167 private void addElement(IAdaptable element, IWorkingSet ws) { 168 addToMap(fElementToWorkingSet, element, ws); 169 IResource resource= (IResource)element.getAdapter(IResource.class); 170 if (resource != null) { 171 addToMap(fResourceToWorkingSet, resource, ws); 172 } 173 } 174 private void removeElement(IAdaptable element, IWorkingSet ws) { 175 removeFromMap(fElementToWorkingSet, element, ws); 176 IResource resource= (IResource)element.getAdapter(IResource.class); 177 if (resource != null) { 178 removeFromMap(fResourceToWorkingSet, resource, ws); 179 } 180 } 181 private void addToMap(Map map, IAdaptable key, IWorkingSet value) { 182 Object obj= map.get(key); 183 if (obj == null) { 184 map.put(key, value); 185 } else if (obj instanceof IWorkingSet) { 186 List l= new ArrayList (2); 187 l.add(obj); 188 l.add(value); 189 map.put(key, l); 190 } else if (obj instanceof List ) { 191 ((List )obj).add(value); 192 } 193 } 194 private void removeFromMap(Map map, IAdaptable key, IWorkingSet value) { 195 Object current= map.get(key); 196 if (current == null) { 197 return; 198 } else if (current instanceof List ) { 199 List list= (List )current; 200 list.remove(value); 201 switch (list.size()) { 202 case 0: 203 map.remove(key); 204 break; 205 case 1: 206 map.put(key, list.get(0)); 207 break; 208 } 209 } else if (current == value) { 210 map.remove(key); 211 } 212 } 213 private Object getFirstElement(Map map, Object key) { 214 Object obj= map.get(key); 215 if (obj instanceof List ) 216 return ((List )obj).get(0); 217 return obj; 218 } 219 private List getAllElements(Map map, Object key) { 220 Object obj= map.get(key); 221 if (obj instanceof List ) 222 return (List )obj; 223 if (obj == null) 224 return Collections.EMPTY_LIST; 225 List result= new ArrayList (1); 226 result.add(obj); 227 return result; 228 } 229 } 230 231 234 public WorkingSetModel(IMemento memento) { 235 fLocalWorkingSetManager= PlatformUI.getWorkbench().createLocalWorkingSetManager(); 236 addListenersToWorkingSetManagers(); 237 fActiveWorkingSets= new ArrayList (2); 238 239 if (memento == null || ! restoreState(memento)) { 240 IWorkingSet others= fLocalWorkingSetManager.createWorkingSet(WorkingSetMessages.WorkingSetModel_others_name, new IAdaptable[0]); 241 others.setId(OthersWorkingSetUpdater.ID); 242 fLocalWorkingSetManager.addWorkingSet(others); 243 fActiveWorkingSets.add(others); 244 } 245 Assert.isNotNull(fOthersWorkingSetUpdater); 246 247 fElementMapper.rebuild(getActiveWorkingSets()); 248 fOthersWorkingSetUpdater.updateElements(); 249 } 250 251 private void addListenersToWorkingSetManagers() { 252 fListeners= new ListenerList(ListenerList.IDENTITY); 253 fWorkingSetManagerListener= new IPropertyChangeListener() { 254 public void propertyChange(PropertyChangeEvent event) { 255 workingSetManagerChanged(event); 256 } 257 }; 258 PlatformUI.getWorkbench().getWorkingSetManager().addPropertyChangeListener(fWorkingSetManagerListener); 259 fLocalWorkingSetManager.addPropertyChangeListener(fWorkingSetManagerListener); 260 } 261 262 public void dispose() { 263 if (fWorkingSetManagerListener != null) { 264 PlatformUI.getWorkbench().getWorkingSetManager().removePropertyChangeListener(fWorkingSetManagerListener); 265 fLocalWorkingSetManager.removePropertyChangeListener(fWorkingSetManagerListener); 266 fLocalWorkingSetManager.dispose(); 267 fWorkingSetManagerListener= null; 268 } 269 } 270 271 273 public IAdaptable[] getChildren(IWorkingSet workingSet) { 274 return workingSet.getElements(); 275 } 276 277 public Object getParent(Object element) { 278 if (element instanceof IWorkingSet && fActiveWorkingSets.contains(element)) 279 return this; 280 return fElementMapper.getFirstWorkingSet(element); 281 } 282 283 public Object [] getAllParents(Object element) { 284 if (element instanceof IWorkingSet && fActiveWorkingSets.contains(element)) 285 return new Object [] {this}; 286 return fElementMapper.getAllWorkingSets(element).toArray(); 287 } 288 289 public Object [] addWorkingSets(Object [] elements) { 290 List result= null; 291 for (int i= 0; i < elements.length; i++) { 292 Object element= elements[i]; 293 List sets= null; 294 if (element instanceof IResource) { 295 sets= fElementMapper.getAllWorkingSetsForResource((IResource)element); 296 } else { 297 sets= fElementMapper.getAllWorkingSets(element); 298 } 299 if (sets != null && sets.size() > 0) { 300 if (result == null) 301 result= new ArrayList (Arrays.asList(elements)); 302 result.addAll(sets); 303 } 304 } 305 if (result == null) 306 return elements; 307 return result.toArray(); 308 } 309 310 public boolean needsConfiguration() { 311 return !fConfigured && fActiveWorkingSets.size() == 1 && 312 OthersWorkingSetUpdater.ID.equals(((IWorkingSet)fActiveWorkingSets.get(0)).getId()); 313 } 314 315 public void configured() { 316 fConfigured= true; 317 } 318 319 321 326 public void addPropertyChangeListener(IPropertyChangeListener listener) { 327 fListeners.add(listener); 328 } 329 330 335 public void removePropertyChangeListener(IPropertyChangeListener listener) { 336 fListeners.remove(listener); 337 } 338 339 public IWorkingSet[] getActiveWorkingSets() { 340 return (IWorkingSet[])fActiveWorkingSets.toArray(new IWorkingSet[fActiveWorkingSets.size()]); 341 } 342 343 public IWorkingSet[] getAllWorkingSets() { 344 List result= new ArrayList (); 345 result.addAll(fActiveWorkingSets); 346 IWorkingSet[] locals= fLocalWorkingSetManager.getWorkingSets(); 347 for (int i= 0; i < locals.length; i++) { 348 if (!result.contains(locals[i])) 349 result.add(locals[i]); 350 } 351 IWorkingSet[] globals= PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSets(); 352 for (int i= 0; i < globals.length; i++) { 353 if (!result.contains(globals[i])) 354 result.add(globals[i]); 355 } 356 return (IWorkingSet[])result.toArray(new IWorkingSet[result.size()]); 357 } 358 359 public void setActiveWorkingSets(IWorkingSet[] workingSets) { 360 fActiveWorkingSets= new ArrayList (Arrays.asList(workingSets)); 361 fElementMapper.rebuild(getActiveWorkingSets()); 362 fOthersWorkingSetUpdater.updateElements(); 363 fireEvent(new PropertyChangeEvent(this, CHANGE_WORKING_SET_MODEL_CONTENT, null, null)); 364 } 365 366 public void saveState(IMemento memento) { 367 memento.putString(TAG_CONFIGURED, Boolean.toString(fConfigured)); 368 fLocalWorkingSetManager.saveState(memento.createChild(TAG_LOCAL_WORKING_SET_MANAGER)); 369 for (Iterator iter= fActiveWorkingSets.iterator(); iter.hasNext();) { 370 IMemento active= memento.createChild(TAG_ACTIVE_WORKING_SET); 371 IWorkingSet workingSet= (IWorkingSet)iter.next(); 372 active.putString(TAG_WORKING_SET_NAME, workingSet.getName()); 373 } 374 } 375 376 public List getNonProjectTopLevelElements() { 377 return fElementMapper.getNonProjectTopLevelElements(); 378 } 379 380 385 private boolean restoreState(IMemento memento) { 386 String configured= memento.getString(TAG_CONFIGURED); 387 if (configured == null) 388 return false; 389 390 fConfigured= Boolean.valueOf(configured).booleanValue(); 391 fLocalWorkingSetManager.restoreState(memento.getChild(TAG_LOCAL_WORKING_SET_MANAGER)); 392 393 IMemento[] actives= memento.getChildren(TAG_ACTIVE_WORKING_SET); 394 for (int i= 0; i < actives.length; i++) { 395 String name= actives[i].getString(TAG_WORKING_SET_NAME); 396 if (name != null) { 397 IWorkingSet ws= fLocalWorkingSetManager.getWorkingSet(name); 398 if (ws == null) { 399 ws= PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSet(name); 400 } 401 if (ws != null) { 402 fActiveWorkingSets.add(ws); 403 } 404 } 405 } 406 return true; 407 } 408 private void workingSetManagerChanged(PropertyChangeEvent event) { 409 String property= event.getProperty(); 410 if (IWorkingSetManager.CHANGE_WORKING_SET_UPDATER_INSTALLED.equals(property) && event.getSource() == fLocalWorkingSetManager) { 411 IWorkingSetUpdater updater= (IWorkingSetUpdater)event.getNewValue(); 412 if (updater instanceof OthersWorkingSetUpdater) { 413 fOthersWorkingSetUpdater= (OthersWorkingSetUpdater)updater; 414 fOthersWorkingSetUpdater.init(this); 415 } 416 return; 417 } 418 if (!isAffected(event)) 420 return; 421 422 if (IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE.equals(property)) { 423 IWorkingSet workingSet= (IWorkingSet)event.getNewValue(); 424 IAdaptable[] elements= fElementMapper.refresh(workingSet); 425 if (elements != null) { 426 fireEvent(event); 427 } 428 } else if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)) { 429 IWorkingSet workingSet= (IWorkingSet)event.getOldValue(); 430 List elements= new ArrayList (fActiveWorkingSets); 431 elements.remove(workingSet); 432 setActiveWorkingSets((IWorkingSet[])elements.toArray(new IWorkingSet[elements.size()])); 433 } else if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE.equals(property)) { 434 fireEvent(event); 435 } 436 } 437 438 private void fireEvent(PropertyChangeEvent event) { 439 Object [] listeners= fListeners.getListeners(); 440 for (int i= 0; i < listeners.length; i++) { 441 ((IPropertyChangeListener)listeners[i]).propertyChange(event); 442 } 443 } 444 445 private boolean isAffected(PropertyChangeEvent event) { 446 if (fActiveWorkingSets == null) 447 return false; 448 Object oldValue= event.getOldValue(); 449 Object newValue= event.getNewValue(); 450 if ((oldValue != null && fActiveWorkingSets.contains(oldValue)) 451 || (newValue != null && fActiveWorkingSets.contains(newValue))) { 452 return true; 453 } 454 return false; 455 } 456 457 public boolean isActiveWorkingSet(IWorkingSet changedWorkingSet) { 458 return fActiveWorkingSets.contains(changedWorkingSet); 459 } 460 } 461 | Popular Tags |