1 11 package org.eclipse.jdt.internal.ui.typehierarchy; 12 13 import java.lang.reflect.InvocationTargetException ; 14 import java.util.ArrayList ; 15 import java.util.List ; 16 17 import org.eclipse.core.runtime.IProgressMonitor; 18 import org.eclipse.core.runtime.OperationCanceledException; 19 20 import org.eclipse.jface.operation.IRunnableContext; 21 import org.eclipse.jface.operation.IRunnableWithProgress; 22 23 import org.eclipse.jdt.core.*; 24 25 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 26 import org.eclipse.jdt.internal.ui.JavaPlugin; 27 28 31 public class TypeHierarchyLifeCycle implements ITypeHierarchyChangedListener, IElementChangedListener { 32 33 private boolean fHierarchyRefreshNeeded; 34 private ITypeHierarchy fHierarchy; 35 private IJavaElement fInputElement; 36 private boolean fIsSuperTypesOnly; 37 38 private List fChangeListeners; 39 40 public TypeHierarchyLifeCycle() { 41 this(false); 42 } 43 44 public TypeHierarchyLifeCycle(boolean isSuperTypesOnly) { 45 fHierarchy= null; 46 fInputElement= null; 47 fIsSuperTypesOnly= isSuperTypesOnly; 48 fChangeListeners= new ArrayList (2); 49 } 50 51 public ITypeHierarchy getHierarchy() { 52 return fHierarchy; 53 } 54 55 public IJavaElement getInputElement() { 56 return fInputElement; 57 } 58 59 60 public void freeHierarchy() { 61 if (fHierarchy != null) { 62 fHierarchy.removeTypeHierarchyChangedListener(this); 63 JavaCore.removeElementChangedListener(this); 64 fHierarchy= null; 65 fInputElement= null; 66 } 67 } 68 69 public void removeChangedListener(ITypeHierarchyLifeCycleListener listener) { 70 fChangeListeners.remove(listener); 71 } 72 73 public void addChangedListener(ITypeHierarchyLifeCycleListener listener) { 74 if (!fChangeListeners.contains(listener)) { 75 fChangeListeners.add(listener); 76 } 77 } 78 79 private void fireChange(IType[] changedTypes) { 80 for (int i= fChangeListeners.size()-1; i>=0; i--) { 81 ITypeHierarchyLifeCycleListener curr= (ITypeHierarchyLifeCycleListener) fChangeListeners.get(i); 82 curr.typeHierarchyChanged(this, changedTypes); 83 } 84 } 85 86 public void ensureRefreshedTypeHierarchy(final IJavaElement element, IRunnableContext context) throws InvocationTargetException , InterruptedException { 87 if (element == null || !element.exists()) { 88 freeHierarchy(); 89 return; 90 } 91 boolean hierachyCreationNeeded= (fHierarchy == null || !element.equals(fInputElement)); 92 93 if (hierachyCreationNeeded || fHierarchyRefreshNeeded) { 94 95 IRunnableWithProgress op= new IRunnableWithProgress() { 96 public void run(IProgressMonitor pm) throws InvocationTargetException , InterruptedException { 97 try { 98 doHierarchyRefresh(element, pm); 99 } catch (JavaModelException e) { 100 throw new InvocationTargetException (e); 101 } catch (OperationCanceledException e) { 102 throw new InterruptedException (); 103 } 104 } 105 }; 106 fHierarchyRefreshNeeded= true; 107 context.run(true, true, op); 108 fHierarchyRefreshNeeded= false; 109 } 110 } 111 112 private ITypeHierarchy createTypeHierarchy(IJavaElement element, IProgressMonitor pm) throws JavaModelException { 113 if (element.getElementType() == IJavaElement.TYPE) { 114 IType type= (IType) element; 115 if (fIsSuperTypesOnly) { 116 return type.newSupertypeHierarchy(pm); 117 } else { 118 return type.newTypeHierarchy(pm); 119 } 120 } else { 121 IRegion region= JavaCore.newRegion(); 122 if (element.getElementType() == IJavaElement.JAVA_PROJECT) { 123 IPackageFragmentRoot[] roots= ((IJavaProject) element).getPackageFragmentRoots(); 125 for (int i= 0; i < roots.length; i++) { 126 if (!roots[i].isExternal()) { 127 region.add(roots[i]); 128 } 129 } 130 } else if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { 131 IPackageFragmentRoot[] roots= element.getJavaProject().getPackageFragmentRoots(); 132 String name= element.getElementName(); 133 for (int i= 0; i < roots.length; i++) { 134 IPackageFragment pack= roots[i].getPackageFragment(name); 135 if (pack.exists()) { 136 region.add(pack); 137 } 138 } 139 } else { 140 region.add(element); 141 } 142 IJavaProject jproject= element.getJavaProject(); 143 return jproject.newTypeHierarchy(region, pm); 144 } 145 } 146 147 148 public synchronized void doHierarchyRefresh(IJavaElement element, IProgressMonitor pm) throws JavaModelException { 149 boolean hierachyCreationNeeded= (fHierarchy == null || !element.equals(fInputElement)); 150 if (fHierarchy != null) { 153 fHierarchy.removeTypeHierarchyChangedListener(this); 154 JavaCore.removeElementChangedListener(this); 155 } 156 if (hierachyCreationNeeded) { 157 fHierarchy= createTypeHierarchy(element, pm); 158 if (pm != null && pm.isCanceled()) { 159 throw new OperationCanceledException(); 160 } 161 fInputElement= element; 162 } else { 163 fHierarchy.refresh(pm); 164 } 165 fHierarchy.addTypeHierarchyChangedListener(this); 166 JavaCore.addElementChangedListener(this); 167 fHierarchyRefreshNeeded= false; 168 } 169 170 173 public void typeHierarchyChanged(ITypeHierarchy typeHierarchy) { 174 fHierarchyRefreshNeeded= true; 175 fireChange(null); 176 } 177 178 181 public void elementChanged(ElementChangedEvent event) { 182 if (fChangeListeners.isEmpty()) { 183 return; 184 } 185 186 if (fHierarchyRefreshNeeded) { 187 return; 188 } else { 189 ArrayList changedTypes= new ArrayList (); 190 processDelta(event.getDelta(), changedTypes); 191 if (changedTypes.size() > 0) { 192 fireChange((IType[]) changedTypes.toArray(new IType[changedTypes.size()])); 193 } 194 } 195 } 196 197 200 private void processDelta(IJavaElementDelta delta, ArrayList changedTypes) { 201 IJavaElement element= delta.getElement(); 202 switch (element.getElementType()) { 203 case IJavaElement.TYPE: 204 processTypeDelta((IType) element, changedTypes); 205 processChildrenDelta(delta, changedTypes); break; 207 case IJavaElement.JAVA_MODEL: 208 case IJavaElement.JAVA_PROJECT: 209 case IJavaElement.PACKAGE_FRAGMENT_ROOT: 210 case IJavaElement.PACKAGE_FRAGMENT: 211 processChildrenDelta(delta, changedTypes); 212 break; 213 case IJavaElement.COMPILATION_UNIT: 214 ICompilationUnit cu= (ICompilationUnit)element; 215 if (!JavaModelUtil.isPrimary(cu)) { 216 return; 217 } 218 219 if (delta.getKind() == IJavaElementDelta.CHANGED && isPossibleStructuralChange(delta.getFlags())) { 220 try { 221 if (cu.exists()) { 222 IType[] types= cu.getAllTypes(); 223 for (int i= 0; i < types.length; i++) { 224 processTypeDelta(types[i], changedTypes); 225 } 226 } 227 } catch (JavaModelException e) { 228 JavaPlugin.log(e); 229 } 230 } else { 231 processChildrenDelta(delta, changedTypes); 232 } 233 break; 234 case IJavaElement.CLASS_FILE: 235 if (delta.getKind() == IJavaElementDelta.CHANGED) { 236 IType type= ((IClassFile) element).getType(); 237 processTypeDelta(type, changedTypes); 238 } else { 239 processChildrenDelta(delta, changedTypes); 240 } 241 break; 242 } 243 } 244 245 private boolean isPossibleStructuralChange(int flags) { 246 return (flags & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_FINE_GRAINED)) == IJavaElementDelta.F_CONTENT; 247 } 248 249 private void processTypeDelta(IType type, ArrayList changedTypes) { 250 if (getHierarchy().contains(type)) { 251 changedTypes.add(type); 252 } 253 } 254 255 private void processChildrenDelta(IJavaElementDelta delta, ArrayList changedTypes) { 256 IJavaElementDelta[] children= delta.getAffectedChildren(); 257 for (int i= 0; i < children.length; i++) { 258 processDelta(children[i], changedTypes); } 260 } 261 262 263 } 264 | Popular Tags |