PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.jdt.ui.source_3.7.1.r371_v20110824-0800/org/eclipse/jdt/internal/ui/browsing/JavaBrowsingContentProvider.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 550 lines | 434 code | 62 blank | 54 comment | 206 complexity | 8202c62f4685c0d222155ae3d4db337b MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2011 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.jdt.internal.ui.browsing;
  12. import java.util.ArrayList;
  13. import java.util.Arrays;
  14. import java.util.Collection;
  15. import java.util.Iterator;
  16. import java.util.List;
  17. import org.eclipse.swt.widgets.Control;
  18. import org.eclipse.swt.widgets.Display;
  19. import org.eclipse.core.resources.IResource;
  20. import org.eclipse.jface.viewers.AbstractTreeViewer;
  21. import org.eclipse.jface.viewers.IBasicPropertyConstants;
  22. import org.eclipse.jface.viewers.ListViewer;
  23. import org.eclipse.jface.viewers.StructuredViewer;
  24. import org.eclipse.jface.viewers.TableViewer;
  25. import org.eclipse.jface.viewers.Viewer;
  26. import org.eclipse.jdt.core.ElementChangedEvent;
  27. import org.eclipse.jdt.core.IClassFile;
  28. import org.eclipse.jdt.core.ICompilationUnit;
  29. import org.eclipse.jdt.core.IElementChangedListener;
  30. import org.eclipse.jdt.core.IImportContainer;
  31. import org.eclipse.jdt.core.IJavaElement;
  32. import org.eclipse.jdt.core.IJavaElementDelta;
  33. import org.eclipse.jdt.core.IJavaProject;
  34. import org.eclipse.jdt.core.IPackageDeclaration;
  35. import org.eclipse.jdt.core.IPackageFragment;
  36. import org.eclipse.jdt.core.IPackageFragmentRoot;
  37. import org.eclipse.jdt.core.IParent;
  38. import org.eclipse.jdt.core.ISourceReference;
  39. import org.eclipse.jdt.core.IType;
  40. import org.eclipse.jdt.core.IWorkingCopy;
  41. import org.eclipse.jdt.core.JavaCore;
  42. import org.eclipse.jdt.core.JavaModelException;
  43. import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
  44. import org.eclipse.jdt.internal.ui.JavaPlugin;
  45. class JavaBrowsingContentProvider extends StandardJavaElementContentProvider implements IElementChangedListener {
  46. private StructuredViewer fViewer;
  47. private Object fInput;
  48. private JavaBrowsingPart fBrowsingPart;
  49. private int fReadsInDisplayThread;
  50. public JavaBrowsingContentProvider(boolean provideMembers, JavaBrowsingPart browsingPart) {
  51. super(provideMembers);
  52. fBrowsingPart= browsingPart;
  53. fViewer= fBrowsingPart.getViewer();
  54. JavaCore.addElementChangedListener(this);
  55. }
  56. @Override
  57. public boolean hasChildren(Object element) {
  58. startReadInDisplayThread();
  59. try{
  60. return super.hasChildren(element);
  61. } finally {
  62. finishedReadInDisplayThread();
  63. }
  64. }
  65. @Override
  66. public Object[] getChildren(Object element) {
  67. if (!exists(element))
  68. return NO_CHILDREN;
  69. startReadInDisplayThread();
  70. try {
  71. if (element instanceof Collection) {
  72. Collection<?> elements= (Collection<?>)element;
  73. if (elements.isEmpty())
  74. return NO_CHILDREN;
  75. Object[] result= new Object[0];
  76. Iterator<?> iter= ((Collection<?>)element).iterator();
  77. while (iter.hasNext()) {
  78. Object[] children= getChildren(iter.next());
  79. if (children != NO_CHILDREN)
  80. result= concatenate(result, children);
  81. }
  82. return result;
  83. }
  84. if (element instanceof IPackageFragment)
  85. return getPackageContents((IPackageFragment)element);
  86. if (fProvideMembers && element instanceof IType)
  87. return getChildren((IType)element);
  88. if (fProvideMembers && element instanceof ISourceReference && element instanceof IParent)
  89. return removeImportAndPackageDeclarations(super.getChildren(element));
  90. if (element instanceof IJavaProject)
  91. return getPackageFragmentRoots((IJavaProject)element);
  92. return super.getChildren(element);
  93. } catch (JavaModelException e) {
  94. return NO_CHILDREN;
  95. } finally {
  96. finishedReadInDisplayThread();
  97. }
  98. }
  99. private Object[] getPackageContents(IPackageFragment fragment) throws JavaModelException {
  100. ISourceReference[] sourceRefs;
  101. if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
  102. sourceRefs= fragment.getCompilationUnits();
  103. }
  104. else {
  105. IClassFile[] classFiles= fragment.getClassFiles();
  106. List<IClassFile> topLevelClassFile= new ArrayList<IClassFile>();
  107. for (int i= 0; i < classFiles.length; i++) {
  108. IType type= classFiles[i].getType();
  109. if (type != null && type.getDeclaringType() == null && !type.isAnonymous() && !type.isLocal())
  110. topLevelClassFile.add(classFiles[i]);
  111. }
  112. sourceRefs= topLevelClassFile.toArray(new ISourceReference[topLevelClassFile.size()]);
  113. }
  114. Object[] result= new Object[0];
  115. for (int i= 0; i < sourceRefs.length; i++)
  116. result= concatenate(result, removeImportAndPackageDeclarations(getChildren(sourceRefs[i])));
  117. return concatenate(result, fragment.getNonJavaResources());
  118. }
  119. private Object[] removeImportAndPackageDeclarations(Object[] members) {
  120. ArrayList<Object> tempResult= new ArrayList<Object>(members.length);
  121. for (int i= 0; i < members.length; i++)
  122. if (!(members[i] instanceof IImportContainer) && !(members[i] instanceof IPackageDeclaration))
  123. tempResult.add(members[i]);
  124. return tempResult.toArray();
  125. }
  126. private Object[] getChildren(IType type) throws JavaModelException{
  127. IParent parent;
  128. if (type.isBinary())
  129. parent= type.getClassFile();
  130. else {
  131. parent= type.getCompilationUnit();
  132. }
  133. if (type.getDeclaringType() != null)
  134. return type.getChildren();
  135. // Add import declarations
  136. IJavaElement[] members= parent.getChildren();
  137. ArrayList<IJavaElement> tempResult= new ArrayList<IJavaElement>(members.length);
  138. for (int i= 0; i < members.length; i++)
  139. if ((members[i] instanceof IImportContainer))
  140. tempResult.add(members[i]);
  141. tempResult.addAll(Arrays.asList(type.getChildren()));
  142. return tempResult.toArray();
  143. }
  144. @Override
  145. protected Object[] getPackageFragmentRoots(IJavaProject project) throws JavaModelException {
  146. if (!project.getProject().isOpen())
  147. return NO_CHILDREN;
  148. IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
  149. List<IJavaElement> list= new ArrayList<IJavaElement>(roots.length);
  150. // filter out package fragments that correspond to projects and
  151. // replace them with the package fragments directly
  152. for (int i= 0; i < roots.length; i++) {
  153. IPackageFragmentRoot root= roots[i];
  154. if (!root.isExternal()) {
  155. IJavaElement[] children= root.getChildren();
  156. for (int k= 0; k < children.length; k++)
  157. list.add(children[k]);
  158. }
  159. else if (hasChildren(root)) {
  160. list.add(root);
  161. }
  162. }
  163. return concatenate(list.toArray(), project.getNonJavaResources());
  164. }
  165. // ---------------- Element change handling
  166. /* (non-Javadoc)
  167. * Method declared on IContentProvider.
  168. */
  169. @Override
  170. public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
  171. super.inputChanged(viewer, oldInput, newInput);
  172. if (newInput instanceof Collection) {
  173. // Get a template object from the collection
  174. Collection<?> col= (Collection<?>)newInput;
  175. if (!col.isEmpty())
  176. newInput= col.iterator().next();
  177. else
  178. newInput= null;
  179. }
  180. fInput= newInput;
  181. }
  182. /* (non-Javadoc)
  183. * Method declared on IContentProvider.
  184. */
  185. @Override
  186. public void dispose() {
  187. super.dispose();
  188. JavaCore.removeElementChangedListener(this);
  189. }
  190. /* (non-Javadoc)
  191. * Method declared on IElementChangedListener.
  192. */
  193. public void elementChanged(final ElementChangedEvent event) {
  194. try {
  195. processDelta(event.getDelta());
  196. } catch(JavaModelException e) {
  197. JavaPlugin.log(e.getStatus());
  198. }
  199. }
  200. /**
  201. * Processes a delta recursively. When more than two children are affected the
  202. * tree is fully refreshed starting at this node. The delta is processed in the
  203. * current thread but the viewer updates are posted to the UI thread.
  204. */
  205. protected void processDelta(IJavaElementDelta delta) throws JavaModelException {
  206. int kind= delta.getKind();
  207. int flags= delta.getFlags();
  208. final IJavaElement element= delta.getElement();
  209. final boolean isElementValidForView= fBrowsingPart.isValidElement(element);
  210. if (!getProvideWorkingCopy() && element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy())
  211. return;
  212. if (element != null && element.getElementType() == IJavaElement.COMPILATION_UNIT && !isOnClassPath((ICompilationUnit)element))
  213. return;
  214. // handle open and closing of a solution or project
  215. if (((flags & IJavaElementDelta.F_CLOSED) != 0) || ((flags & IJavaElementDelta.F_OPENED) != 0)) {
  216. postRefresh(null);
  217. return;
  218. }
  219. if (kind == IJavaElementDelta.REMOVED) {
  220. Object parent= internalGetParent(element);
  221. if (isElementValidForView) {
  222. if (element instanceof IClassFile) {
  223. postRemove(((IClassFile)element).getType());
  224. } else if (element instanceof ICompilationUnit && !((ICompilationUnit)element).isWorkingCopy()) {
  225. postRefresh(null);
  226. } else if (element instanceof ICompilationUnit && ((ICompilationUnit)element).isWorkingCopy()) {
  227. if (getProvideWorkingCopy())
  228. postRefresh(null);
  229. } else if (parent instanceof ICompilationUnit && getProvideWorkingCopy() && !((ICompilationUnit)parent).isWorkingCopy()) {
  230. if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
  231. // working copy removed from system - refresh
  232. postRefresh(null);
  233. }
  234. } else if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy() && parent != null && parent.equals(fInput))
  235. // closed editor - removing working copy
  236. postRefresh(null);
  237. else
  238. postRemove(element);
  239. }
  240. if (fBrowsingPart.isAncestorOf(element, fInput)) {
  241. if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
  242. postAdjustInputAndSetSelection(((IJavaElement) fInput).getPrimaryElement());
  243. } else
  244. postAdjustInputAndSetSelection(null);
  245. }
  246. if (fInput != null && fInput.equals(element))
  247. postRefresh(null);
  248. if (parent instanceof IPackageFragment && fBrowsingPart.isValidElement(parent)) {
  249. // refresh if package gets empty (might be filtered)
  250. if (isPackageFragmentEmpty((IPackageFragment)parent) && fViewer.testFindItem(parent) != null)
  251. postRefresh(null);
  252. }
  253. return;
  254. }
  255. if (kind == IJavaElementDelta.ADDED && delta.getMovedFromElement() != null && element instanceof ICompilationUnit)
  256. return;
  257. if (kind == IJavaElementDelta.ADDED) {
  258. if (isElementValidForView) {
  259. Object parent= internalGetParent(element);
  260. if (element instanceof IClassFile) {
  261. postAdd(parent, ((IClassFile)element).getType());
  262. } else if (element instanceof ICompilationUnit && !((ICompilationUnit)element).isWorkingCopy()) {
  263. postAdd(parent, ((ICompilationUnit)element).getTypes());
  264. } else if (parent instanceof ICompilationUnit && getProvideWorkingCopy() && !((ICompilationUnit)parent).isWorkingCopy()) {
  265. // do nothing
  266. } else if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
  267. // new working copy comes to live
  268. postRefresh(null);
  269. } else
  270. postAdd(parent, element);
  271. } else if (fInput == null) {
  272. IJavaElement newInput= fBrowsingPart.findInputForJavaElement(element);
  273. if (newInput != null)
  274. postAdjustInputAndSetSelection(element);
  275. } else if (element instanceof IType && fBrowsingPart.isValidInput(element)) {
  276. IJavaElement cu1= element.getAncestor(IJavaElement.COMPILATION_UNIT);
  277. IJavaElement cu2= ((IJavaElement)fInput).getAncestor(IJavaElement.COMPILATION_UNIT);
  278. if (cu1 != null && cu2 != null && cu1.equals(cu2))
  279. postAdjustInputAndSetSelection(element);
  280. }
  281. return;
  282. }
  283. if (kind == IJavaElementDelta.CHANGED) {
  284. if (fInput != null && fInput.equals(element) && (flags & IJavaElementDelta.F_CHILDREN) != 0 && (flags & IJavaElementDelta.F_FINE_GRAINED) != 0) {
  285. postRefresh(null, true);
  286. return;
  287. }
  288. if (isElementValidForView && (flags & IJavaElementDelta.F_MODIFIERS) != 0) {
  289. postUpdateIcon(element);
  290. }
  291. }
  292. if (isClassPathChange(delta))
  293. // throw the towel and do a full refresh
  294. postRefresh(null);
  295. if ((flags & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0 && fInput instanceof IJavaElement) {
  296. IPackageFragmentRoot pkgRoot= (IPackageFragmentRoot)element;
  297. IJavaElement inputsParent= ((IJavaElement)fInput).getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
  298. if (pkgRoot.equals(inputsParent))
  299. postRefresh(null);
  300. }
  301. // the source attachment of a JAR has changed
  302. if (element instanceof IPackageFragmentRoot && (((flags & IJavaElementDelta.F_SOURCEATTACHED) != 0 || ((flags & IJavaElementDelta.F_SOURCEDETACHED)) != 0)))
  303. postUpdateIcon(element);
  304. IJavaElementDelta[] affectedChildren= delta.getAffectedChildren();
  305. if (affectedChildren.length > 1) {
  306. // a package fragment might become non empty refresh from the parent
  307. if (element instanceof IPackageFragment) {
  308. IJavaElement parent= (IJavaElement)internalGetParent(element);
  309. // avoid posting a refresh to an invisible parent
  310. if (element.equals(fInput)) {
  311. postRefresh(element);
  312. } else {
  313. postRefresh(parent);
  314. }
  315. }
  316. // more than one child changed, refresh from here downwards
  317. if (element instanceof IPackageFragmentRoot && isElementValidForView) {
  318. postRefresh(skipProjectPackageFragmentRoot((IPackageFragmentRoot)element));
  319. return;
  320. }
  321. }
  322. for (int i= 0; i < affectedChildren.length; i++) {
  323. processDelta(affectedChildren[i]);
  324. }
  325. }
  326. private boolean isOnClassPath(ICompilationUnit element) throws JavaModelException {
  327. IJavaProject project= element.getJavaProject();
  328. if (project == null || !project.exists())
  329. return false;
  330. return project.isOnClasspath(element);
  331. }
  332. /**
  333. * Updates the package icon
  334. */
  335. private void postUpdateIcon(final IJavaElement element) {
  336. postRunnable(new Runnable() {
  337. public void run() {
  338. Control ctrl= fViewer.getControl();
  339. if (ctrl != null && !ctrl.isDisposed())
  340. fViewer.update(element, new String[]{IBasicPropertyConstants.P_IMAGE});
  341. }
  342. });
  343. }
  344. private void postRefresh(final Object root, final boolean updateLabels) {
  345. postRunnable(new Runnable() {
  346. public void run() {
  347. Control ctrl= fViewer.getControl();
  348. if (ctrl != null && !ctrl.isDisposed())
  349. fViewer.refresh(root, updateLabels);
  350. }
  351. });
  352. }
  353. private void postRefresh(final Object root) {
  354. postRefresh(root, false);
  355. }
  356. private void postAdd(final Object parent, final Object element) {
  357. postAdd(parent, new Object[] {element});
  358. }
  359. private void postAdd(final Object parent, final Object[] elements) {
  360. if (elements == null || elements.length <= 0)
  361. return;
  362. postRunnable(new Runnable() {
  363. public void run() {
  364. Control ctrl= fViewer.getControl();
  365. if (ctrl != null && !ctrl.isDisposed()) {
  366. Object[] newElements= getNewElements(elements);
  367. if (fViewer instanceof AbstractTreeViewer) {
  368. if (fViewer.testFindItem(parent) == null) {
  369. Object root= ((AbstractTreeViewer)fViewer).getInput();
  370. if (root != null)
  371. ((AbstractTreeViewer)fViewer).add(root, newElements);
  372. }
  373. else
  374. ((AbstractTreeViewer)fViewer).add(parent, newElements);
  375. }
  376. else if (fViewer instanceof ListViewer)
  377. ((ListViewer)fViewer).add(newElements);
  378. else if (fViewer instanceof TableViewer)
  379. ((TableViewer)fViewer).add(newElements);
  380. if (fViewer.testFindItem(elements[0]) != null)
  381. fBrowsingPart.adjustInputAndSetSelection(elements[0]);
  382. }
  383. }
  384. });
  385. }
  386. private Object[] getNewElements(Object[] elements) {
  387. int elementsLength= elements.length;
  388. ArrayList<Object> result= new ArrayList<Object>(elementsLength);
  389. for (int i= 0; i < elementsLength; i++) {
  390. Object element= elements[i];
  391. if (fViewer.testFindItem(element) == null)
  392. result.add(element);
  393. }
  394. return result.toArray();
  395. }
  396. private void postRemove(final Object element) {
  397. postRemove(new Object[] {element});
  398. }
  399. private void postRemove(final Object[] elements) {
  400. if (elements.length <= 0)
  401. return;
  402. postRunnable(new Runnable() {
  403. public void run() {
  404. Control ctrl= fViewer.getControl();
  405. if (ctrl != null && !ctrl.isDisposed()) {
  406. if (fViewer instanceof AbstractTreeViewer)
  407. ((AbstractTreeViewer)fViewer).remove(elements);
  408. else if (fViewer instanceof ListViewer)
  409. ((ListViewer)fViewer).remove(elements);
  410. else if (fViewer instanceof TableViewer)
  411. ((TableViewer)fViewer).remove(elements);
  412. }
  413. }
  414. });
  415. }
  416. private void postAdjustInputAndSetSelection(final Object element) {
  417. postRunnable(new Runnable() {
  418. public void run() {
  419. Control ctrl= fViewer.getControl();
  420. if (ctrl != null && !ctrl.isDisposed()) {
  421. ctrl.setRedraw(false);
  422. fBrowsingPart.adjustInputAndSetSelection(element);
  423. ctrl.setRedraw(true);
  424. }
  425. }
  426. });
  427. }
  428. protected void startReadInDisplayThread() {
  429. if (isDisplayThread())
  430. fReadsInDisplayThread++;
  431. }
  432. protected void finishedReadInDisplayThread() {
  433. if (isDisplayThread())
  434. fReadsInDisplayThread--;
  435. }
  436. private boolean isDisplayThread() {
  437. Control ctrl= fViewer.getControl();
  438. if (ctrl == null)
  439. return false;
  440. Display currentDisplay= Display.getCurrent();
  441. return currentDisplay != null && currentDisplay.equals(ctrl.getDisplay());
  442. }
  443. private void postRunnable(final Runnable r) {
  444. Control ctrl= fViewer.getControl();
  445. if (ctrl != null && !ctrl.isDisposed()) {
  446. fBrowsingPart.setProcessSelectionEvents(false);
  447. try {
  448. if (isDisplayThread() && fReadsInDisplayThread == 0)
  449. ctrl.getDisplay().syncExec(r);
  450. else
  451. ctrl.getDisplay().asyncExec(r);
  452. } finally {
  453. fBrowsingPart.setProcessSelectionEvents(true);
  454. }
  455. }
  456. }
  457. /**
  458. * Returns the parent for the element.
  459. * <p>
  460. * Note: This method will return a working copy if the
  461. * parent is a working copy. The super class implementation
  462. * returns the original element instead.
  463. * </p>
  464. */
  465. @Override
  466. protected Object internalGetParent(Object element) {
  467. if (element instanceof IJavaProject) {
  468. return ((IJavaProject)element).getJavaModel();
  469. }
  470. // try to map resources to the containing package fragment
  471. if (element instanceof IResource) {
  472. IResource parent= ((IResource)element).getParent();
  473. Object jParent= JavaCore.create(parent);
  474. if (jParent != null)
  475. return jParent;
  476. return parent;
  477. }
  478. // for package fragments that are contained in a project package fragment
  479. // we have to skip the package fragment root as the parent.
  480. if (element instanceof IPackageFragment) {
  481. IPackageFragmentRoot parent= (IPackageFragmentRoot)((IPackageFragment)element).getParent();
  482. return skipProjectPackageFragmentRoot(parent);
  483. }
  484. if (element instanceof IJavaElement)
  485. return ((IJavaElement)element).getParent();
  486. return null;
  487. }
  488. }