001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.browsing;
011:
012: import java.util.ArrayList;
013: import java.util.Arrays;
014: import java.util.Iterator;
015: import java.util.List;
016:
017: import org.eclipse.core.runtime.CoreException;
018:
019: import org.eclipse.core.resources.IFolder;
020: import org.eclipse.core.resources.IResource;
021:
022: import org.eclipse.swt.widgets.Control;
023: import org.eclipse.swt.widgets.Display;
024:
025: import org.eclipse.jface.viewers.ITreeContentProvider;
026: import org.eclipse.jface.viewers.StructuredViewer;
027: import org.eclipse.jface.viewers.TreeViewer;
028:
029: import org.eclipse.jdt.core.ICompilationUnit;
030: import org.eclipse.jdt.core.IJavaElement;
031: import org.eclipse.jdt.core.IJavaElementDelta;
032: import org.eclipse.jdt.core.IJavaProject;
033: import org.eclipse.jdt.core.IPackageFragment;
034: import org.eclipse.jdt.core.IPackageFragmentRoot;
035: import org.eclipse.jdt.core.JavaCore;
036: import org.eclipse.jdt.core.JavaModelException;
037:
038: import org.eclipse.jdt.internal.ui.JavaPlugin;
039:
040: /**
041: * Tree content provider for the hierarchical layout in the packages view.
042: * <p>
043: * XXX: The standard Java browsing part content provider needs and calls
044: * the browsing part/view. This class currently doesn't need to do so
045: * but might be required to later.
046: * </p>
047: */
048: class PackagesViewHierarchicalContentProvider extends
049: LogicalPackagesProvider implements ITreeContentProvider {
050:
051: public PackagesViewHierarchicalContentProvider(
052: StructuredViewer viewer) {
053: super (viewer);
054: }
055:
056: /*
057: * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(Object)
058: */
059: public Object[] getChildren(Object parentElement) {
060: try {
061: if (parentElement instanceof IJavaElement) {
062: IJavaElement iJavaElement = (IJavaElement) parentElement;
063: int type = iJavaElement.getElementType();
064:
065: switch (type) {
066: case IJavaElement.JAVA_PROJECT: {
067:
068: //create new element mapping
069: fMapToLogicalPackage.clear();
070: fMapToPackageFragments.clear();
071: IJavaProject project = (IJavaProject) parentElement;
072:
073: IPackageFragment[] topLevelChildren = getTopLevelChildrenByElementName(project
074: .getPackageFragments());
075: List list = new ArrayList();
076: for (int i = 0; i < topLevelChildren.length; i++) {
077: IPackageFragment fragment = topLevelChildren[i];
078:
079: IJavaElement el = fragment.getParent();
080: if (el instanceof IPackageFragmentRoot) {
081: IPackageFragmentRoot root = (IPackageFragmentRoot) el;
082: if (!root.isArchive() || !root.isExternal())
083: list.add(fragment);
084: }
085: }
086:
087: IPackageFragmentRoot[] packageFragmentRoots = project
088: .getPackageFragmentRoots();
089: List folders = new ArrayList();
090: for (int i = 0; i < packageFragmentRoots.length; i++) {
091: IPackageFragmentRoot root = packageFragmentRoots[i];
092: IResource resource = root
093: .getUnderlyingResource();
094: if (resource != null
095: && resource instanceof IFolder) {
096: folders
097: .addAll(getFolders(((IFolder) resource)
098: .members()));
099: }
100: }
101:
102: Object[] logicalPackages = combineSamePackagesIntoLogialPackages((IPackageFragment[]) list
103: .toArray(new IPackageFragment[list.size()]));
104: if (folders.size() > 0) {
105: if (logicalPackages.length > 0)
106: folders.addAll(Arrays
107: .asList(logicalPackages));
108: return folders.toArray();
109: } else {
110: return logicalPackages;
111: }
112: }
113:
114: case IJavaElement.PACKAGE_FRAGMENT_ROOT: {
115: IPackageFragmentRoot root = (IPackageFragmentRoot) parentElement;
116:
117: //create new element mapping
118: fMapToLogicalPackage.clear();
119: fMapToPackageFragments.clear();
120: IResource resource = root.getUnderlyingResource();
121: if (root.isArchive()) {
122: IPackageFragment[] fragments = new IPackageFragment[0];
123: IJavaElement[] els = root.getChildren();
124: fragments = getTopLevelChildrenByElementName(els);
125: addFragmentsToMap(fragments);
126: return fragments;
127:
128: } else if (resource != null
129: && resource instanceof IFolder) {
130: List children = getFoldersAndElements(((IFolder) resource)
131: .members());
132:
133: IPackageFragment defaultPackage = root
134: .getPackageFragment(""); //$NON-NLS-1$
135: if (defaultPackage.exists())
136: children.add(defaultPackage);
137:
138: addFragmentsToMap(children);
139: return children.toArray();
140: } else {
141: return NO_CHILDREN;
142: }
143: }
144:
145: case IJavaElement.PACKAGE_FRAGMENT: {
146: IPackageFragment packageFragment = (IPackageFragment) parentElement;
147: if (packageFragment.isDefaultPackage())
148: return NO_CHILDREN;
149:
150: IPackageFragmentRoot parent = (IPackageFragmentRoot) packageFragment
151: .getParent();
152: IPackageFragment[] fragments = findNextLevelChildrenByElementName(
153: parent, packageFragment);
154:
155: addFragmentsToMap(fragments);
156:
157: Object[] nonJavaResources = packageFragment
158: .getNonJavaResources();
159: if (nonJavaResources.length == 0) {
160: return fragments;
161: }
162: ArrayList combined = new ArrayList();
163: combined.addAll(Arrays.asList(fragments));
164: for (int i = 0; i < nonJavaResources.length; i++) {
165: Object curr = nonJavaResources[i];
166: if (curr instanceof IFolder) {
167: combined.add(curr);
168: }
169: }
170: return combined.toArray();
171: }
172: }
173:
174: //@Improve: rewrite using concatenate
175: } else if (parentElement instanceof LogicalPackage) {
176:
177: List children = new ArrayList();
178: LogicalPackage logicalPackage = (LogicalPackage) parentElement;
179: IPackageFragment[] elements = logicalPackage
180: .getFragments();
181: for (int i = 0; i < elements.length; i++) {
182: IPackageFragment fragment = elements[i];
183: IPackageFragment[] objects = findNextLevelChildrenByElementName(
184: (IPackageFragmentRoot) fragment.getParent(),
185: fragment);
186: children.addAll(Arrays.asList(objects));
187: }
188: return combineSamePackagesIntoLogialPackages((IPackageFragment[]) children
189: .toArray(new IPackageFragment[children.size()]));
190: } else if (parentElement instanceof IFolder) {
191: IFolder folder = (IFolder) parentElement;
192: IResource[] resources = folder.members();
193: List children = getFoldersAndElements(resources);
194: addFragmentsToMap(children);
195: return children.toArray();
196: }
197:
198: } catch (JavaModelException e) {
199: return NO_CHILDREN;
200: } catch (CoreException e) {
201: return NO_CHILDREN;
202: }
203: return NO_CHILDREN;
204: }
205:
206: private void addFragmentsToMap(List elements) {
207: List packageFragments = new ArrayList();
208: for (Iterator iter = elements.iterator(); iter.hasNext();) {
209: Object elem = iter.next();
210: if (elem instanceof IPackageFragment)
211: packageFragments.add(elem);
212: }
213: addFragmentsToMap((IPackageFragment[]) packageFragments
214: .toArray(new IPackageFragment[packageFragments.size()]));
215: }
216:
217: private List getFoldersAndElements(IResource[] resources)
218: throws CoreException {
219: List list = new ArrayList();
220: for (int i = 0; i < resources.length; i++) {
221: IResource resource = resources[i];
222:
223: if (resource instanceof IFolder) {
224: IFolder folder = (IFolder) resource;
225: IJavaElement element = JavaCore.create(folder);
226:
227: if (element instanceof IPackageFragment) {
228: list.add(element);
229: } else {
230: list.add(folder);
231: }
232: }
233: }
234: return list;
235: }
236:
237: private List getFolders(IResource[] resources) throws CoreException {
238: List list = new ArrayList();
239: for (int i = 0; i < resources.length; i++) {
240: IResource resource = resources[i];
241:
242: if (resource instanceof IFolder) {
243: IFolder folder = (IFolder) resource;
244: IJavaElement element = JavaCore.create(folder);
245:
246: if (element == null) {
247: list.add(folder);
248: }
249: }
250: }
251: return list;
252: }
253:
254: private IPackageFragment[] findNextLevelChildrenByElementName(
255: IPackageFragmentRoot parent, IPackageFragment fragment) {
256: List list = new ArrayList();
257: try {
258:
259: IJavaElement[] children = parent.getChildren();
260: String fragmentname = fragment.getElementName();
261: for (int i = 0; i < children.length; i++) {
262: IJavaElement element = children[i];
263: if (element instanceof IPackageFragment) {
264: IPackageFragment frag = (IPackageFragment) element;
265:
266: String name = element.getElementName();
267: if (name.length() > fragmentname.length()
268: && name.charAt(fragmentname.length()) == '.'
269: && frag.exists()
270: && !IPackageFragment.DEFAULT_PACKAGE_NAME
271: .equals(fragmentname)
272: && name.startsWith(fragmentname)
273: && !name.equals(fragmentname)) {
274: String tail = name.substring(fragmentname
275: .length() + 1);
276: if (!IPackageFragment.DEFAULT_PACKAGE_NAME
277: .equals(tail)
278: && tail.indexOf('.') == -1) {
279: list.add(frag);
280: }
281: }
282: }
283: }
284:
285: } catch (JavaModelException e) {
286: JavaPlugin.log(e);
287: }
288: return (IPackageFragment[]) list
289: .toArray(new IPackageFragment[list.size()]);
290: }
291:
292: private IPackageFragment[] getTopLevelChildrenByElementName(
293: IJavaElement[] elements) {
294: List topLevelElements = new ArrayList();
295: for (int i = 0; i < elements.length; i++) {
296: IJavaElement iJavaElement = elements[i];
297: //if the name of the PackageFragment is the top level package it will contain no "." separators
298: if (iJavaElement instanceof IPackageFragment
299: && iJavaElement.getElementName().indexOf('.') == -1) {
300: topLevelElements.add(iJavaElement);
301: }
302: }
303: return (IPackageFragment[]) topLevelElements
304: .toArray(new IPackageFragment[topLevelElements.size()]);
305: }
306:
307: /*
308: * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(Object)
309: */
310: public Object getParent(Object element) {
311:
312: try {
313: if (element instanceof IPackageFragment) {
314: IPackageFragment fragment = (IPackageFragment) element;
315: if (!fragment.exists())
316: return null;
317: Object parent = getHierarchicalParent(fragment);
318: if (parent instanceof IPackageFragment) {
319: IPackageFragment pkgFragment = (IPackageFragment) parent;
320: LogicalPackage logicalPkg = findLogicalPackage(pkgFragment);
321: if (logicalPkg != null)
322: return logicalPkg;
323: else {
324: LogicalPackage lp = createLogicalPackage(pkgFragment);
325: if (lp == null)
326: return pkgFragment;
327: else
328: return lp;
329: }
330: }
331: return parent;
332:
333: } else if (element instanceof LogicalPackage) {
334: LogicalPackage el = (LogicalPackage) element;
335: IPackageFragment fragment = el.getFragments()[0];
336: Object parent = getHierarchicalParent(fragment);
337:
338: if (parent instanceof IPackageFragment) {
339: IPackageFragment pkgFragment = (IPackageFragment) parent;
340: LogicalPackage logicalPkg = findLogicalPackage(pkgFragment);
341: if (logicalPkg != null)
342: return logicalPkg;
343: else {
344: LogicalPackage lp = createLogicalPackage(pkgFragment);
345: if (lp == null)
346: return pkgFragment;
347: else
348: return lp;
349: }
350: } else
351: return fragment.getJavaProject();
352: } else if (element instanceof IFolder) {
353: IFolder folder = (IFolder) element;
354: IResource res = folder.getParent();
355:
356: IJavaElement el = JavaCore.create(res);
357: if (el != null) {
358: return el;
359: } else {
360: return res;
361: }
362: }
363:
364: } catch (JavaModelException e) {
365: JavaPlugin.log(e);
366: }
367: return null;
368: }
369:
370: /*
371: * Check if the given IPackageFragment should be the member of a
372: * LogicalPackage and if so creates the LogicalPackage and adds it to the
373: * map.
374: */
375: private LogicalPackage createLogicalPackage(
376: IPackageFragment pkgFragment) {
377: if (!fInputIsProject)
378: return null;
379:
380: List fragments = new ArrayList();
381: try {
382: IPackageFragmentRoot[] roots = pkgFragment.getJavaProject()
383: .getPackageFragmentRoots();
384: for (int i = 0; i < roots.length; i++) {
385: IPackageFragmentRoot root = roots[i];
386: IPackageFragment fragment = root
387: .getPackageFragment(pkgFragment
388: .getElementName());
389: if (fragment.exists() && !fragment.equals(pkgFragment))
390: fragments.add(fragment);
391: }
392: if (!fragments.isEmpty()) {
393: LogicalPackage logicalPackage = new LogicalPackage(
394: pkgFragment);
395: fMapToLogicalPackage.put(getKey(pkgFragment),
396: logicalPackage);
397: Iterator iter = fragments.iterator();
398: while (iter.hasNext()) {
399: IPackageFragment f = (IPackageFragment) iter.next();
400: if (logicalPackage.belongs(f)) {
401: logicalPackage.add(f);
402: fMapToLogicalPackage.put(getKey(f),
403: logicalPackage);
404: }
405: }
406:
407: return logicalPackage;
408: }
409:
410: } catch (JavaModelException e) {
411: JavaPlugin.log(e);
412: }
413:
414: return null;
415: }
416:
417: private Object getHierarchicalParent(IPackageFragment fragment)
418: throws JavaModelException {
419: IJavaElement parent = fragment.getParent();
420:
421: if ((parent instanceof IPackageFragmentRoot) && parent.exists()) {
422: IPackageFragmentRoot root = (IPackageFragmentRoot) parent;
423: if (root.isArchive() || !fragment.exists()) {
424: return findNextLevelParentByElementName(fragment);
425: } else {
426: IResource resource = fragment.getUnderlyingResource();
427: if ((resource != null) && (resource instanceof IFolder)) {
428: IFolder folder = (IFolder) resource;
429: IResource res = folder.getParent();
430:
431: IJavaElement el = JavaCore.create(res);
432: if (el != null) {
433: return el;
434: } else {
435: return res;
436: }
437: }
438: }
439: }
440: return parent;
441: }
442:
443: private Object findNextLevelParentByElementName(
444: IPackageFragment child) {
445: String name = child.getElementName();
446:
447: int index = name.lastIndexOf('.');
448: if (index != -1) {
449: String realParentName = name.substring(0, index);
450: IPackageFragment element = ((IPackageFragmentRoot) child
451: .getParent()).getPackageFragment(realParentName);
452: if (element.exists()) {
453: return element;
454: }
455: }
456: return child.getParent();
457: }
458:
459: /*
460: * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(Object)
461: */
462: public boolean hasChildren(Object element) {
463:
464: if (element instanceof IPackageFragment) {
465: IPackageFragment fragment = (IPackageFragment) element;
466: if (fragment.isDefaultPackage() || !fragment.exists())
467: return false;
468: }
469: return getChildren(element).length > 0;
470: }
471:
472: /*
473: * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(Object)
474: */
475: public Object[] getElements(Object inputElement) {
476: return getChildren(inputElement);
477: }
478:
479: protected void processDelta(IJavaElementDelta delta)
480: throws JavaModelException {
481:
482: int kind = delta.getKind();
483: final IJavaElement element = delta.getElement();
484:
485: if (isClassPathChange(delta)) {
486: Object input = fViewer.getInput();
487: if (input != null) {
488: if (fInputIsProject
489: && input.equals(element.getJavaProject())) {
490: postRefresh(input);
491: return;
492: } else if (!fInputIsProject && input.equals(element)) {
493: if (element.exists())
494: postRefresh(input);
495: else
496: postRemove(input);
497: return;
498: }
499: }
500: }
501:
502: if (kind == IJavaElementDelta.REMOVED) {
503: Object input = fViewer.getInput();
504: if (input != null && input.equals(element)) {
505: postRemove(input);
506: return;
507: }
508: }
509:
510: if (element instanceof IPackageFragment) {
511: final IPackageFragment frag = (IPackageFragment) element;
512:
513: //if fragment was in LogicalPackage refresh,
514: //otherwise just remove
515: if (kind == IJavaElementDelta.REMOVED) {
516: removeElement(frag);
517: return;
518:
519: } else if (kind == IJavaElementDelta.ADDED) {
520:
521: Object parent = getParent(frag);
522: addElement(frag, parent);
523: return;
524:
525: } else if (kind == IJavaElementDelta.CHANGED) {
526: //just refresh
527: LogicalPackage logicalPkg = findLogicalPackage(frag);
528: //in case changed object is filtered out
529: if (logicalPkg != null)
530: postRefresh(findElementToRefresh(logicalPkg));
531: else
532: postRefresh(findElementToRefresh(frag));
533: return;
534: }
535: }
536:
537: processAffectedChildren(delta);
538: }
539:
540: private Object findElementToRefresh(Object object) {
541: Object toBeRefreshed = object;
542: if (fViewer.testFindItem(object) == null) {
543: Object parent = getParent(object);
544: if (parent instanceof IPackageFragmentRoot
545: && fInputIsProject)
546: parent = ((IPackageFragmentRoot) parent)
547: .getJavaProject();
548:
549: if (parent != null)
550: toBeRefreshed = parent;
551: }
552: return toBeRefreshed;
553: }
554:
555: private void processAffectedChildren(IJavaElementDelta delta)
556: throws JavaModelException {
557: IJavaElementDelta[] affectedChildren = delta
558: .getAffectedChildren();
559: for (int i = 0; i < affectedChildren.length; i++) {
560: if (!(affectedChildren[i] instanceof ICompilationUnit)) {
561: processDelta(affectedChildren[i]);
562: }
563: }
564: }
565:
566: private void postAdd(final Object child, final Object parent) {
567: postRunnable(new Runnable() {
568: public void run() {
569: Control ctrl = fViewer.getControl();
570: if (ctrl != null && !ctrl.isDisposed()) {
571: ((TreeViewer) fViewer).add(parent, child);
572: }
573: }
574: });
575: }
576:
577: private void postRemove(final Object object) {
578: postRunnable(new Runnable() {
579: public void run() {
580: Control ctrl = fViewer.getControl();
581: if (ctrl != null && !ctrl.isDisposed()) {
582: ((TreeViewer) fViewer).remove(object);
583: }
584: }
585: });
586: }
587:
588: private void postRefresh(final Object object) {
589: postRunnable(new Runnable() {
590: public void run() {
591: Control ctrl = fViewer.getControl();
592: if (ctrl != null && !ctrl.isDisposed()) {
593: ((TreeViewer) fViewer).refresh(object);
594: }
595: }
596: });
597: }
598:
599: private void postRunnable(final Runnable r) {
600: Control ctrl = fViewer.getControl();
601: if (ctrl != null && !ctrl.isDisposed()) {
602: // fBrowsingPart.setProcessSelectionEvents(false);
603: try {
604: Display currentDisplay = Display.getCurrent();
605: if (currentDisplay != null
606: && currentDisplay.equals(ctrl.getDisplay()))
607: ctrl.getDisplay().syncExec(r);
608: else
609: ctrl.getDisplay().asyncExec(r);
610: } finally {
611: // fBrowsingPart.setProcessSelectionEvents(true);
612: }
613: }
614: }
615:
616: private void addElement(IPackageFragment frag, Object parent) {
617:
618: String key = getKey(frag);
619: LogicalPackage lp = (LogicalPackage) fMapToLogicalPackage
620: .get(key);
621:
622: //if fragment must be added to an existing LogicalPackage
623: if (lp != null && lp.belongs(frag)) {
624: lp.add(frag);
625: return;
626: }
627:
628: //if a new LogicalPackage must be created
629: IPackageFragment iPackageFragment = (IPackageFragment) fMapToPackageFragments
630: .get(key);
631: if (iPackageFragment != null && !iPackageFragment.equals(frag)) {
632: lp = new LogicalPackage(iPackageFragment);
633: lp.add(frag);
634: //add new LogicalPackage to LogicalPackages map
635: fMapToLogicalPackage.put(key, lp);
636:
637: //determine who to refresh
638: if (parent instanceof IPackageFragmentRoot) {
639: IPackageFragmentRoot root = (IPackageFragmentRoot) parent;
640: if (fInputIsProject) {
641: postRefresh(root.getJavaProject());
642: } else {
643: postRefresh(root);
644: }
645: } else {
646: //@Improve: Should this be replaced by a refresh?
647: postAdd(lp, parent);
648: postRemove(iPackageFragment);
649: }
650:
651: }
652: //if this is a new Package Fragment
653: else {
654: fMapToPackageFragments.put(key, frag);
655:
656: //determine who to refresh
657: if (parent instanceof IPackageFragmentRoot) {
658: IPackageFragmentRoot root = (IPackageFragmentRoot) parent;
659: if (fInputIsProject) {
660: postAdd(frag, root.getJavaProject());
661: } else
662: postAdd(frag, root);
663: } else {
664: postAdd(frag, parent);
665: }
666: }
667: }
668:
669: private void removeElement(IPackageFragment frag) {
670:
671: String key = getKey(frag);
672: LogicalPackage lp = (LogicalPackage) fMapToLogicalPackage
673: .get(key);
674:
675: if (lp != null) {
676: lp.remove(frag);
677: //if the LogicalPackage needs to revert back to a PackageFragment
678: //remove it from the LogicalPackages map and add the PackageFragment
679: //to the PackageFragment map
680: if (lp.getFragments().length == 1) {
681: IPackageFragment fragment = lp.getFragments()[0];
682: fMapToPackageFragments.put(key, fragment);
683: fMapToLogicalPackage.remove(key);
684:
685: //remove the LogicalPackage from viewer
686: postRemove(lp);
687:
688: Object parent = getParent(fragment);
689: if (parent instanceof IPackageFragmentRoot) {
690: parent = ((IPackageFragmentRoot) parent)
691: .getJavaProject();
692: }
693: postAdd(fragment, parent);
694: }
695:
696: } else {
697: //remove the fragment from the fragment map and viewer
698: IPackageFragment fragment = (IPackageFragment) fMapToPackageFragments
699: .get(key);
700: if (fragment != null && fragment.equals(frag)) {
701: fMapToPackageFragments.remove(key);
702: postRemove(frag);
703: }
704: }
705: }
706: }
|