2d66b7d72e1fcbe24ce9ac7d6ba77207fc803032
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / ui / JavaElementSorter.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.ui;
12
13 import java.text.Collator;
14
15 import net.sourceforge.phpdt.core.Flags;
16 import net.sourceforge.phpdt.core.IField;
17 import net.sourceforge.phpdt.core.IJavaElement;
18 import net.sourceforge.phpdt.core.IMember;
19 import net.sourceforge.phpdt.core.IMethod;
20 import net.sourceforge.phpdt.core.IPackageFragment;
21 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
22 import net.sourceforge.phpdt.core.IType;
23 import net.sourceforge.phpdt.core.JavaModelException;
24 import net.sourceforge.phpdt.core.Signature;
25 import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
26 import net.sourceforge.phpdt.internal.corext.util.JdtFlags;
27 import net.sourceforge.phpdt.internal.ui.preferences.MembersOrderPreferenceCache;
28 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
29 import net.sourceforge.phpeclipse.ui.WebUI;
30
31 import org.eclipse.core.resources.IContainer;
32 import org.eclipse.core.resources.IFile;
33 import org.eclipse.core.resources.IProject;
34 import org.eclipse.core.resources.IStorage;
35 import org.eclipse.core.runtime.IAdaptable;
36 import org.eclipse.core.runtime.IPath;
37 import org.eclipse.jface.viewers.ContentViewer;
38 import org.eclipse.jface.viewers.IBaseLabelProvider;
39 import org.eclipse.jface.viewers.ILabelProvider;
40 import org.eclipse.jface.viewers.Viewer;
41 import org.eclipse.jface.viewers.ViewerSorter;
42 import org.eclipse.ui.model.IWorkbenchAdapter;
43
44 /**
45  * Sorter for Java elements. Ordered by element category, then by element name.
46  * Package fragment roots are sorted as ordered on the classpath.
47  * 
48  * <p>
49  * This class may be instantiated; it is not intended to be subclassed.
50  * </p>
51  * 
52  * @since 2.0
53  */
54 public class JavaElementSorter extends ViewerSorter {
55
56         private static final int PROJECTS = 1;
57
58         private static final int PACKAGEFRAGMENTROOTS = 2;
59
60         private static final int PACKAGEFRAGMENT = 3;
61
62         private static final int COMPILATIONUNITS = 4;
63
64         private static final int CLASSFILES = 5;
65
66         private static final int RESOURCEFOLDERS = 7;
67
68         private static final int RESOURCES = 8;
69
70         private static final int STORAGE = 9;
71
72         private static final int PACKAGE_DECL = 10;
73
74         private static final int IMPORT_CONTAINER = 11;
75
76         private static final int IMPORT_DECLARATION = 12;
77
78         // Includes all categories ordered using the OutlineSortOrderPage:
79         // types, initializers, methods & fields
80         private static final int MEMBERSOFFSET = 15;
81
82         private static final int JAVAELEMENTS = 50;
83
84         private static final int OTHERS = 51;
85
86         private MembersOrderPreferenceCache fMemberOrderCache;
87
88         /**
89          * Constructor.
90          */
91         public JavaElementSorter() {
92                 super(null); // delay initialization of collator
93                 fMemberOrderCache = WebUI.getDefault()
94                                 .getMemberOrderPreferenceCache();
95         }
96
97         /**
98          * @deprecated Bug 22518. Method never used: does not override
99          *             ViewerSorter#isSorterProperty(Object, String). Method could
100          *             be removed, but kept for API compatibility.
101          */
102         public boolean isSorterProperty(Object element, Object property) {
103                 return true;
104         }
105
106         /*
107          * @see ViewerSorter#category
108          */
109         public int category(Object element) {
110                 if (element instanceof IJavaElement) {
111                         try {
112                                 IJavaElement je = (IJavaElement) element;
113
114                                 switch (je.getElementType()) {
115                                 case IJavaElement.METHOD: {
116                                         IMethod method = (IMethod) je;
117                                         if (method.isConstructor()) {
118                                                 return getMemberCategory(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX);
119                                         }
120                                         int flags = method.getFlags();
121                                         if (Flags.isStatic(flags))
122                                                 return getMemberCategory(MembersOrderPreferenceCache.STATIC_METHODS_INDEX);
123                                         else
124                                                 return getMemberCategory(MembersOrderPreferenceCache.METHOD_INDEX);
125                                 }
126                                 case IJavaElement.FIELD: {
127                                         int flags = ((IField) je).getFlags();
128                                         if (Flags.isStatic(flags))
129                                                 return getMemberCategory(MembersOrderPreferenceCache.STATIC_FIELDS_INDEX);
130                                         else
131                                                 return getMemberCategory(MembersOrderPreferenceCache.FIELDS_INDEX);
132                                 }
133                                         // case IJavaElement.INITIALIZER :
134                                         // {
135                                         // int flags= ((IInitializer) je).getFlags();
136                                         // if (Flags.isStatic(flags))
137                                         // return
138                                         // getMemberCategory(MembersOrderPreferenceCache.STATIC_INIT_INDEX);
139                                         // else
140                                         // return
141                                         // getMemberCategory(MembersOrderPreferenceCache.INIT_INDEX);
142                                         // }
143                                 case IJavaElement.TYPE:
144                                         return getMemberCategory(MembersOrderPreferenceCache.TYPE_INDEX);
145                                 case IJavaElement.PACKAGE_DECLARATION:
146                                         return PACKAGE_DECL;
147                                 case IJavaElement.IMPORT_CONTAINER:
148                                         return IMPORT_CONTAINER;
149                                 case IJavaElement.IMPORT_DECLARATION:
150                                         return IMPORT_DECLARATION;
151                                 case IJavaElement.PACKAGE_FRAGMENT:
152                                         IPackageFragment pack = (IPackageFragment) je;
153                                         if (pack.getParent().getResource() instanceof IProject) {
154                                                 return PACKAGEFRAGMENTROOTS;
155                                         }
156                                         return PACKAGEFRAGMENT;
157                                 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
158                                         return PACKAGEFRAGMENTROOTS;
159                                 case IJavaElement.JAVA_PROJECT:
160                                         return PROJECTS;
161                                 case IJavaElement.CLASS_FILE:
162                                         return CLASSFILES;
163                                 case IJavaElement.COMPILATION_UNIT:
164                                         return COMPILATIONUNITS;
165                                 }
166
167                         } catch (JavaModelException e) {
168                                 if (!e.isDoesNotExist())
169                                         PHPeclipsePlugin.log(e);
170                         }
171                         return JAVAELEMENTS;
172                 } else if (element instanceof IFile) {
173                         return RESOURCES;
174                 } else if (element instanceof IProject) {
175                         return PROJECTS;
176                 } else if (element instanceof IContainer) {
177                         return RESOURCEFOLDERS;
178                 } else if (element instanceof IStorage) {
179                         return STORAGE;
180                 }
181                 // else if (element instanceof ClassPathContainer) {
182                 // return PACKAGEFRAGMENTROOTS;
183                 // }
184                 return OTHERS;
185         }
186
187         private int getMemberCategory(int kind) {
188                 int offset = fMemberOrderCache.getCategoryIndex(kind);
189                 return offset + MEMBERSOFFSET;
190         }
191
192         /*
193          * @see ViewerSorter#compare
194          */
195         public int compare(Viewer viewer, Object e1, Object e2) {
196                 int cat1 = category(e1);
197                 int cat2 = category(e2);
198
199                 if (cat1 != cat2)
200                         return cat1 - cat2;
201
202                 if (cat1 == PROJECTS) {
203                         IWorkbenchAdapter a1 = (IWorkbenchAdapter) ((IAdaptable) e1)
204                                         .getAdapter(IWorkbenchAdapter.class);
205                         IWorkbenchAdapter a2 = (IWorkbenchAdapter) ((IAdaptable) e2)
206                                         .getAdapter(IWorkbenchAdapter.class);
207                         return getCollator().compare(a1.getLabel(e1), a2.getLabel(e2));
208                 }
209
210                 if (cat1 == PACKAGEFRAGMENTROOTS) {
211                         IPackageFragmentRoot root1 = getPackageFragmentRoot(e1);
212                         IPackageFragmentRoot root2 = getPackageFragmentRoot(e2);
213                         if (root1 == null) {
214                                 if (root2 == null) {
215                                         return 0;
216                                 } else {
217                                         return 1;
218                                 }
219                         } else if (root2 == null) {
220                                 return -1;
221                         }
222                         if (!root1.getPath().equals(root2.getPath())) {
223                                 int p1 = getClassPathIndex(root1);
224                                 int p2 = getClassPathIndex(root2);
225                                 if (p1 != p2) {
226                                         return p1 - p2;
227                                 }
228                         }
229                         e1 = root1; // normalize classpath container to root
230                         e2 = root2;
231                 }
232                 // non - java resources are sorted using the label from the viewers
233                 // label provider
234                 if (cat1 == PROJECTS || cat1 == RESOURCES || cat1 == RESOURCEFOLDERS
235                                 || cat1 == STORAGE || cat1 == OTHERS) {
236                         return compareWithLabelProvider(viewer, e1, e2);
237                 }
238
239                 if (e1 instanceof IMember) {
240                         if (fMemberOrderCache.isSortByVisibility()) {
241                                 try {
242                                         int flags1 = JdtFlags.getVisibilityCode((IMember) e1);
243                                         int flags2 = JdtFlags.getVisibilityCode((IMember) e2);
244                                         int vis = fMemberOrderCache.getVisibilityIndex(flags1)
245                                                         - fMemberOrderCache.getVisibilityIndex(flags2);
246                                         if (vis != 0) {
247                                                 return vis;
248                                         }
249                                 } catch (JavaModelException ignore) {
250                                 }
251                         }
252                 }
253
254                 String name1 = ((IJavaElement) e1).getElementName();
255                 String name2 = ((IJavaElement) e2).getElementName();
256
257                 if (e1 instanceof IType) { // handle anonymous types
258                         if (name1.length() == 0) {
259                                 if (name2.length() == 0) {
260                                         try {
261                                                 return getCollator().compare(
262                                                                 ((IType) e1).getSuperclassName(),
263                                                                 ((IType) e2).getSuperclassName());
264                                         } catch (JavaModelException e) {
265                                                 return 0;
266                                         }
267                                 } else {
268                                         return 1;
269                                 }
270                         } else if (name2.length() == 0) {
271                                 return -1;
272                         }
273                 }
274
275                 int cmp = getCollator().compare(name1, name2);
276                 if (cmp != 0) {
277                         return cmp;
278                 }
279
280                 if (e1 instanceof IMethod) {
281                         String[] params1 = ((IMethod) e1).getParameterTypes();
282                         String[] params2 = ((IMethod) e2).getParameterTypes();
283                         int len = Math.min(params1.length, params2.length);
284                         for (int i = 0; i < len; i++) {
285                                 cmp = getCollator().compare(Signature.toString(params1[i]),
286                                                 Signature.toString(params2[i]));
287                                 if (cmp != 0) {
288                                         return cmp;
289                                 }
290                         }
291                         return params1.length - params2.length;
292                 }
293                 return 0;
294         }
295
296         private IPackageFragmentRoot getPackageFragmentRoot(Object element) {
297                 // if (element instanceof ClassPathContainer) {
298                 // // return first package fragment root from the container
299                 // ClassPathContainer cp= (ClassPathContainer)element;
300                 // Object[] roots= cp.getPackageFragmentRoots();
301                 // if (roots.length > 0)
302                 // return (IPackageFragmentRoot)roots[0];
303                 // // non resolvable - return null
304                 // return null;
305                 // }
306                 return JavaModelUtil.getPackageFragmentRoot((IJavaElement) element);
307         }
308
309         private int compareWithLabelProvider(Viewer viewer, Object e1, Object e2) {
310                 if (viewer == null || !(viewer instanceof ContentViewer)) {
311                         IBaseLabelProvider prov = ((ContentViewer) viewer)
312                                         .getLabelProvider();
313                         if (prov instanceof ILabelProvider) {
314                                 ILabelProvider lprov = (ILabelProvider) prov;
315                                 String name1 = lprov.getText(e1);
316                                 String name2 = lprov.getText(e2);
317                                 if (name1 != null && name2 != null) {
318                                         return getCollator().compare(name1, name2);
319                                 }
320                         }
321                 }
322                 return 0; // can't compare
323         }
324
325         private int getClassPathIndex(IPackageFragmentRoot root) {
326                 try {
327                         IPath rootPath = root.getPath();
328                         IPackageFragmentRoot[] roots = root.getJavaProject()
329                                         .getPackageFragmentRoots();
330                         for (int i = 0; i < roots.length; i++) {
331                                 if (roots[i].getPath().equals(rootPath)) {
332                                         return i;
333                                 }
334                         }
335                 } catch (JavaModelException e) {
336                 }
337
338                 return Integer.MAX_VALUE;
339         }
340
341         /*
342          * (non-Javadoc)
343          * 
344          * @see org.eclipse.jface.viewers.ViewerSorter#getCollator()
345          */
346         public final Collator getCollator() {
347                 if (collator == null) {
348                         collator = Collator.getInstance();
349                 }
350                 return collator;
351         }
352
353 }