upload tizen1.0 source
[sdk/ide/product.git] / org.eclipse.cdt.ui / src / org / eclipse / cdt / internal / ui / search / PDOMSearchTreeContentProvider.java
1 /*******************************************************************************
2  * Copyright (c) 2006, 2009 QNX Software Systems 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  *    QNX - Initial API and implementation
10  *    Markus Schorn (Wind River Systems)
11  *    Ed Swartz (Nokia)
12  *******************************************************************************/
13 package org.eclipse.cdt.internal.ui.search;
14
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.Map;
19 import java.util.Set;
20
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.resources.ResourcesPlugin;
24 import org.eclipse.core.runtime.IPath;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Path;
27 import org.eclipse.core.runtime.Status;
28 import org.eclipse.jface.viewers.ITreeContentProvider;
29 import org.eclipse.jface.viewers.TreeViewer;
30 import org.eclipse.jface.viewers.Viewer;
31
32 import org.eclipse.cdt.core.CCorePlugin;
33 import org.eclipse.cdt.core.index.IIndexFileLocation;
34 import org.eclipse.cdt.core.index.IndexLocationFactory;
35 import org.eclipse.cdt.core.model.CoreModel;
36 import org.eclipse.cdt.core.model.ICElement;
37 import org.eclipse.cdt.core.model.ICProject;
38 import org.eclipse.cdt.core.model.ISourceRoot;
39 import org.eclipse.cdt.ui.CUIPlugin;
40
41 import org.eclipse.cdt.internal.core.resources.ResourceLookup;
42
43 /**
44  * @author Doug Schaefer
45  *
46  */
47 public class PDOMSearchTreeContentProvider implements ITreeContentProvider, IPDOMSearchContentProvider {
48
49         private TreeViewer viewer;
50         private PDOMSearchResult result;
51         private Map<Object, Set<Object>> tree = new HashMap<Object, Set<Object>>();
52         private final PDOMSearchViewPage fPage;
53
54         PDOMSearchTreeContentProvider(PDOMSearchViewPage page) {
55                 fPage= page;
56         }
57
58         public Object[] getChildren(Object parentElement) {
59                 Set<Object> children = tree.get(parentElement);
60                 if (children == null)
61                         return new Object[0];
62                 return children.toArray();
63         }
64
65         public Object getParent(Object element) {
66                 Iterator<Object> p = tree.keySet().iterator();
67                 while (p.hasNext()) {
68                         Object parent = p.next();
69                         Set<Object> children = tree.get(parent);
70                         if (children.contains(element))
71                                 return parent;
72                 }
73                 return null;
74         }
75
76         public boolean hasChildren(Object element) {
77                 return tree.get(element) != null;
78         }
79
80         public Object[] getElements(Object inputElement) {
81                 return getChildren(inputElement);
82         }
83
84         public void dispose() {
85         }
86
87         public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
88                 this.viewer = (TreeViewer)viewer;
89                 this.result = (PDOMSearchResult) newInput;
90                 initialize(result);
91                 viewer.refresh();
92         }
93
94         /**
95          * Add a message to a project node indicating it has no results because indexer is disabled.
96          * @param project
97          */
98         private void insertUnindexedProjectWarningElement(ICProject project) {
99                 insertCElement(project);
100                 insertChild(project, 
101                                 new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID,
102                                                 CSearchMessages.PDOMSearchTreeContentProvider_IndexerNotEnabledWarning));
103         }
104
105         /**
106          * Add a message to a project node indicating it has no results because project is closed
107          * @param project
108          */
109         private void insertClosedProjectWarningElement(ICProject project) {
110                 insertCElement(project);
111                 insertChild(project, 
112                                 new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID,
113                                                 CSearchMessages.PDOMSearchTreeContentProvider_ProjectClosedWarning));
114         }
115         
116         private boolean insertChild(Object parent, Object child) {
117                 Set<Object> children = tree.get(parent);
118                 if (children == null) {
119                         children = new HashSet<Object>();
120                         tree.put(parent, children);
121                 }
122                 return children.add(child);
123         }
124         
125         private void insertSearchElement(PDOMSearchElement element) {
126                 IIndexFileLocation location= element.getLocation();
127                 IFile[] files;
128                 if(location.getFullPath()!=null) {
129                         files= new IFile[] {ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(location.getFullPath()))};
130                 } else {
131                         IPath path= IndexLocationFactory.getAbsolutePath(element.getLocation());
132                         files= ResourceLookup.findFilesForLocation(path);
133                 }
134                 boolean handled= false;
135                 if (files.length > 0) {
136                         for (int j = 0; j < files.length; ++j) {
137                                 ICElement celement = CoreModel.getDefault().create(files[j]);
138                                 if (celement != null) {
139                                         insertChild(celement, element);
140                                         insertCElement(celement);
141                                         handled= true;
142                                 }
143                         }
144                 } 
145                 if (!handled) {
146                         // insert a folder and then the file under that
147                         IPath path = IndexLocationFactory.getAbsolutePath(location);
148                         if (path != null) {
149                                 IPath directory = path.removeLastSegments(1);
150                                 insertChild(location, element);
151                                 insertChild(directory, location);
152                                 insertChild(result, directory);
153                         } else {
154                                 // URI not representable as a file
155                                 insertChild(IPDOMSearchContentProvider.URI_CONTAINER, location.getURI());
156                                 insertChild(result, IPDOMSearchContentProvider.URI_CONTAINER);
157                         }
158                 }
159         }
160         
161         private void insertCElement(ICElement element) {
162                 if (element instanceof ICProject)
163                         insertChild(result, element);
164                 else {
165                         ICElement parent = element.getParent();
166                         if (parent instanceof ISourceRoot && parent.getUnderlyingResource() instanceof IProject)
167                                 // Skip source roots that are projects
168                                 parent = parent.getParent();
169                         insertChild(parent, element);
170                         insertCElement(parent);
171                 }
172         }
173         
174         public void elementsChanged(Object[] elements) {
175                 if (elements != null) {
176                         for (int i = 0; i < elements.length; ++i) {
177                                 PDOMSearchElement element = (PDOMSearchElement)elements[i];
178                                 if (fPage.getDisplayedMatchCount(element) > 0) {
179                                         insertSearchElement(element);
180                                 } else {
181                                         boolean remove = true;
182                                         if (element instanceof ICProject) {
183                                                 ICProject cProject = (ICProject) element;
184                                                 remove = !addProjectWarningIfApplicable(cProject);
185                                         }
186                                         if (remove) {
187                                                 remove(element);
188                                         }
189                                 }
190                         }
191                 }
192                 if (!viewer.getTree().isDisposed()) {
193                         viewer.refresh();
194                 }
195         }
196
197         private boolean addProjectWarningIfApplicable(ICProject cProject) {
198                 if (cProject.getProject().isOpen()) {
199                         if (!CCorePlugin.getIndexManager().isProjectIndexed(cProject)) {
200                                 insertUnindexedProjectWarningElement(cProject);
201                                 return true;
202                         }
203                 } else {
204                         insertClosedProjectWarningElement(cProject);
205                         return true;
206                 }
207                 return false;
208         }
209         
210         public void clear() {
211                 initialize(result);
212         }
213         
214         private void initialize(final PDOMSearchResult result) {
215                 this.result = result;
216                 tree.clear();
217                 if (result != null) {
218                         // if indexer was busy, record that
219                         if (result.wasIndexerBusy()) {
220                                 insertChild(result, IPDOMSearchContentProvider.INCOMPLETE_RESULTS_NODE); 
221                         }
222                         
223                         Object[] elements = result.getElements();
224                         for (int i = 0; i < elements.length; ++i) {
225                                 final PDOMSearchElement element = (PDOMSearchElement)elements[i];
226                                 if (fPage.getDisplayedMatchCount(element) > 0)
227                                         insertSearchElement(element);
228                         }
229
230                         // add all the projects which have no results
231                         ICProject[] projects = ((PDOMSearchQuery)result.getQuery()).getProjects();
232                         for (int i = 0; i < projects.length; ++i) {
233                                 ICProject project = projects[i];
234                                 Object projectResults = tree.get(project);
235                                 if (projectResults == null) {
236                                         addProjectWarningIfApplicable(project);
237                                 }
238                         }
239                 }
240         }
241         
242         protected void remove(Object element) {
243                 Object parent = getParent(element);
244                 if (parent == null)
245                         // reached the search result
246                         return;
247                 
248                 Set<Object> siblings = tree.get(parent);
249                 siblings.remove(element);
250                 
251                 if (siblings.isEmpty()) {
252                         // remove the parent
253                         remove(parent);
254                         tree.remove(parent);
255                 }
256         }
257 }