001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 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.ui;
011:
012: import org.eclipse.core.runtime.IAdaptable;
013: import org.eclipse.core.runtime.IPath;
014:
015: import org.eclipse.core.resources.IContainer;
016: import org.eclipse.core.resources.IFile;
017: import org.eclipse.core.resources.IProject;
018: import org.eclipse.core.resources.IResource;
019: import org.eclipse.core.resources.IStorage;
020:
021: import org.eclipse.jface.viewers.ContentViewer;
022: import org.eclipse.jface.viewers.IBaseLabelProvider;
023: import org.eclipse.jface.viewers.ILabelProvider;
024: import org.eclipse.jface.viewers.Viewer;
025: import org.eclipse.jface.viewers.ViewerComparator;
026:
027: import org.eclipse.ui.model.IWorkbenchAdapter;
028:
029: import org.eclipse.jdt.core.Flags;
030: import org.eclipse.jdt.core.IField;
031: import org.eclipse.jdt.core.IInitializer;
032: import org.eclipse.jdt.core.IJarEntryResource;
033: import org.eclipse.jdt.core.IJavaElement;
034: import org.eclipse.jdt.core.IJavaProject;
035: import org.eclipse.jdt.core.IMember;
036: import org.eclipse.jdt.core.IMethod;
037: import org.eclipse.jdt.core.IPackageFragment;
038: import org.eclipse.jdt.core.IPackageFragmentRoot;
039: import org.eclipse.jdt.core.IType;
040: import org.eclipse.jdt.core.JavaModelException;
041: import org.eclipse.jdt.core.Signature;
042:
043: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
044: import org.eclipse.jdt.internal.corext.util.JdtFlags;
045:
046: import org.eclipse.jdt.internal.ui.JavaPlugin;
047: import org.eclipse.jdt.internal.ui.packageview.PackageFragmentRootContainer;
048: import org.eclipse.jdt.internal.ui.preferences.MembersOrderPreferenceCache;
049:
050: /**
051: * Viewer comparator for Java elements. Ordered by element category, then by element name.
052: * Package fragment roots are sorted as ordered on the classpath.
053: *
054: * <p>
055: * This class may be instantiated; it is not intended to be subclassed.
056: * </p>
057: *
058: * @since 3.3
059: */
060: public class JavaElementComparator extends ViewerComparator {
061:
062: private static final int PROJECTS = 1;
063: private static final int PACKAGEFRAGMENTROOTS = 2;
064: private static final int PACKAGEFRAGMENT = 3;
065:
066: private static final int COMPILATIONUNITS = 4;
067: private static final int CLASSFILES = 5;
068:
069: private static final int RESOURCEFOLDERS = 7;
070: private static final int RESOURCES = 8;
071:
072: private static final int PACKAGE_DECL = 10;
073: private static final int IMPORT_CONTAINER = 11;
074: private static final int IMPORT_DECLARATION = 12;
075:
076: // Includes all categories ordered using the OutlineSortOrderPage:
077: // types, initializers, methods & fields
078: private static final int MEMBERSOFFSET = 15;
079:
080: private static final int JAVAELEMENTS = 50;
081: private static final int OTHERS = 51;
082:
083: private MembersOrderPreferenceCache fMemberOrderCache;
084:
085: /**
086: * Constructor.
087: */
088: public JavaElementComparator() {
089: super (null); // delay initialization of collator
090: fMemberOrderCache = JavaPlugin.getDefault()
091: .getMemberOrderPreferenceCache();
092: }
093:
094: /* (non-Javadoc)
095: * @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object)
096: */
097: public int category(Object element) {
098: if (element instanceof IJavaElement) {
099: try {
100: IJavaElement je = (IJavaElement) element;
101:
102: switch (je.getElementType()) {
103: case IJavaElement.METHOD: {
104: IMethod method = (IMethod) je;
105: if (method.isConstructor()) {
106: return getMemberCategory(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX);
107: }
108: int flags = method.getFlags();
109: if (Flags.isStatic(flags))
110: return getMemberCategory(MembersOrderPreferenceCache.STATIC_METHODS_INDEX);
111: else
112: return getMemberCategory(MembersOrderPreferenceCache.METHOD_INDEX);
113: }
114: case IJavaElement.FIELD: {
115: int flags = ((IField) je).getFlags();
116: if (Flags.isEnum(flags)) {
117: return getMemberCategory(MembersOrderPreferenceCache.ENUM_CONSTANTS_INDEX);
118: }
119: if (Flags.isStatic(flags))
120: return getMemberCategory(MembersOrderPreferenceCache.STATIC_FIELDS_INDEX);
121: else
122: return getMemberCategory(MembersOrderPreferenceCache.FIELDS_INDEX);
123: }
124: case IJavaElement.INITIALIZER: {
125: int flags = ((IInitializer) je).getFlags();
126: if (Flags.isStatic(flags))
127: return getMemberCategory(MembersOrderPreferenceCache.STATIC_INIT_INDEX);
128: else
129: return getMemberCategory(MembersOrderPreferenceCache.INIT_INDEX);
130: }
131: case IJavaElement.TYPE:
132: return getMemberCategory(MembersOrderPreferenceCache.TYPE_INDEX);
133: case IJavaElement.PACKAGE_DECLARATION:
134: return PACKAGE_DECL;
135: case IJavaElement.IMPORT_CONTAINER:
136: return IMPORT_CONTAINER;
137: case IJavaElement.IMPORT_DECLARATION:
138: return IMPORT_DECLARATION;
139: case IJavaElement.PACKAGE_FRAGMENT:
140: return PACKAGEFRAGMENT;
141: case IJavaElement.PACKAGE_FRAGMENT_ROOT:
142: return PACKAGEFRAGMENTROOTS;
143: case IJavaElement.JAVA_PROJECT:
144: return PROJECTS;
145: case IJavaElement.CLASS_FILE:
146: return CLASSFILES;
147: case IJavaElement.COMPILATION_UNIT:
148: return COMPILATIONUNITS;
149: }
150:
151: } catch (JavaModelException e) {
152: if (!e.isDoesNotExist())
153: JavaPlugin.log(e);
154: }
155: return JAVAELEMENTS;
156: } else if (element instanceof IFile) {
157: return RESOURCES;
158: } else if (element instanceof IProject) {
159: return PROJECTS;
160: } else if (element instanceof IContainer) {
161: return RESOURCEFOLDERS;
162: } else if (element instanceof IJarEntryResource) {
163: if (((IJarEntryResource) element).isFile()) {
164: return RESOURCES;
165: }
166: return RESOURCEFOLDERS;
167: } else if (element instanceof PackageFragmentRootContainer) {
168: return PACKAGEFRAGMENTROOTS;
169: }
170: return OTHERS;
171: }
172:
173: private int getMemberCategory(int kind) {
174: int offset = fMemberOrderCache.getCategoryIndex(kind);
175: return offset + MEMBERSOFFSET;
176: }
177:
178: /* (non-Javadoc)
179: * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
180: */
181: public int compare(Viewer viewer, Object e1, Object e2) {
182: int cat1 = category(e1);
183: int cat2 = category(e2);
184:
185: if (needsClasspathComparision(e1, cat1, e2, cat2)) {
186: IPackageFragmentRoot root1 = getPackageFragmentRoot(e1);
187: IPackageFragmentRoot root2 = getPackageFragmentRoot(e2);
188: if (root1 == null) {
189: if (root2 == null) {
190: return 0;
191: } else {
192: return 1;
193: }
194: } else if (root2 == null) {
195: return -1;
196: }
197: // check if not same to avoid expensive class path access
198: if (!root1.getPath().equals(root2.getPath())) {
199: int p1 = getClassPathIndex(root1);
200: int p2 = getClassPathIndex(root2);
201: if (p1 != p2) {
202: return p1 - p2;
203: }
204: }
205: }
206:
207: if (cat1 != cat2)
208: return cat1 - cat2;
209:
210: if (cat1 == PROJECTS || cat1 == RESOURCES
211: || cat1 == RESOURCEFOLDERS || cat1 == OTHERS) {
212: String name1 = getNonJavaElementLabel(viewer, e1);
213: String name2 = getNonJavaElementLabel(viewer, e2);
214: if (name1 != null && name2 != null) {
215: return getComparator().compare(name1, name2);
216: }
217: return 0; // can't compare
218: }
219: // only java elements from this point
220:
221: if (e1 instanceof IMember) {
222: if (fMemberOrderCache.isSortByVisibility()) {
223: try {
224: int flags1 = JdtFlags
225: .getVisibilityCode((IMember) e1);
226: int flags2 = JdtFlags
227: .getVisibilityCode((IMember) e2);
228: int vis = fMemberOrderCache
229: .getVisibilityIndex(flags1)
230: - fMemberOrderCache
231: .getVisibilityIndex(flags2);
232: if (vis != 0) {
233: return vis;
234: }
235: } catch (JavaModelException ignore) {
236: }
237: }
238: }
239:
240: String name1 = getElementName(e1);
241: String name2 = getElementName(e2);
242:
243: if (e1 instanceof IType) { // handle anonymous types
244: if (name1.length() == 0) {
245: if (name2.length() == 0) {
246: try {
247: return getComparator().compare(
248: ((IType) e1).getSuperclassName(),
249: ((IType) e2).getSuperclassName());
250: } catch (JavaModelException e) {
251: return 0;
252: }
253: } else {
254: return 1;
255: }
256: } else if (name2.length() == 0) {
257: return -1;
258: }
259: }
260:
261: int cmp = getComparator().compare(name1, name2);
262: if (cmp != 0) {
263: return cmp;
264: }
265:
266: if (e1 instanceof IMethod) {
267: String[] params1 = ((IMethod) e1).getParameterTypes();
268: String[] params2 = ((IMethod) e2).getParameterTypes();
269: int len = Math.min(params1.length, params2.length);
270: for (int i = 0; i < len; i++) {
271: cmp = getComparator().compare(
272: Signature.toString(params1[i]),
273: Signature.toString(params2[i]));
274: if (cmp != 0) {
275: return cmp;
276: }
277: }
278: return params1.length - params2.length;
279: }
280: return 0;
281: }
282:
283: private IPackageFragmentRoot getPackageFragmentRoot(Object element) {
284: if (element instanceof PackageFragmentRootContainer) {
285: // return first package fragment root from the container
286: PackageFragmentRootContainer cp = (PackageFragmentRootContainer) element;
287: Object[] roots = cp.getPackageFragmentRoots();
288: if (roots.length > 0)
289: return (IPackageFragmentRoot) roots[0];
290: // non resolvable - return null
291: return null;
292: }
293: return JavaModelUtil
294: .getPackageFragmentRoot((IJavaElement) element);
295: }
296:
297: private String getNonJavaElementLabel(Viewer viewer, Object element) {
298: // try to use the workbench adapter for non - java resources or if not available, use the viewers label provider
299: if (element instanceof IResource) {
300: return ((IResource) element).getName();
301: }
302: if (element instanceof IStorage) {
303: return ((IStorage) element).getName();
304: }
305: if (element instanceof IAdaptable) {
306: IWorkbenchAdapter adapter = (IWorkbenchAdapter) ((IAdaptable) element)
307: .getAdapter(IWorkbenchAdapter.class);
308: if (adapter != null) {
309: return adapter.getLabel(element);
310: }
311: }
312: if (viewer instanceof ContentViewer) {
313: IBaseLabelProvider prov = ((ContentViewer) viewer)
314: .getLabelProvider();
315: if (prov instanceof ILabelProvider) {
316: return ((ILabelProvider) prov).getText(element);
317: }
318: }
319: return null;
320: }
321:
322: private int getClassPathIndex(IPackageFragmentRoot root) {
323: try {
324: IPath rootPath = root.getPath();
325: IPackageFragmentRoot[] roots = root.getJavaProject()
326: .getPackageFragmentRoots();
327: for (int i = 0; i < roots.length; i++) {
328: if (roots[i].getPath().equals(rootPath)) {
329: return i;
330: }
331: }
332: } catch (JavaModelException e) {
333: }
334:
335: return Integer.MAX_VALUE;
336: }
337:
338: private boolean needsClasspathComparision(Object e1, int cat1,
339: Object e2, int cat2) {
340: if ((cat1 == PACKAGEFRAGMENTROOTS && cat2 == PACKAGEFRAGMENTROOTS)
341: || (cat1 == PACKAGEFRAGMENT
342: && ((IPackageFragment) e1).getParent()
343: .getResource() instanceof IProject && cat2 == PACKAGEFRAGMENTROOTS)
344: || (cat1 == PACKAGEFRAGMENTROOTS
345: && cat2 == PACKAGEFRAGMENT && ((IPackageFragment) e2)
346: .getParent().getResource() instanceof IProject)) {
347: IJavaProject p1 = getJavaProject(e1);
348: return p1 != null && p1.equals(getJavaProject(e2));
349: }
350: return false;
351: }
352:
353: private IJavaProject getJavaProject(Object element) {
354: if (element instanceof IJavaElement) {
355: return ((IJavaElement) element).getJavaProject();
356: } else if (element instanceof PackageFragmentRootContainer) {
357: return ((PackageFragmentRootContainer) element)
358: .getJavaProject();
359: }
360: return null;
361: }
362:
363: private String getElementName(Object element) {
364: if (element instanceof IJavaElement) {
365: return ((IJavaElement) element).getElementName();
366: } else if (element instanceof PackageFragmentRootContainer) {
367: return ((PackageFragmentRootContainer) element).getLabel();
368: } else {
369: return element.toString();
370: }
371: }
372: }
|