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