1 /*******************************************************************************
2  * Copyright (c) 2003, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  * IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.internal.navigator.extensions;
15 
16 import java.util.ArrayList;
17 import java.util.Set;
18 
19 import org.eclipse.core.runtime.SafeRunner;
20 import org.eclipse.jface.viewers.ITreeContentProvider;
21 import org.eclipse.jface.viewers.ITreePathContentProvider;
22 import org.eclipse.jface.viewers.StructuredViewer;
23 import org.eclipse.jface.viewers.TreePath;
24 import org.eclipse.jface.viewers.Viewer;
25 import org.eclipse.ui.IMemento;
26 import org.eclipse.ui.internal.navigator.NavigatorSafeRunnable;
27 import org.eclipse.ui.navigator.ICommonContentExtensionSite;
28 import org.eclipse.ui.navigator.ICommonContentProvider;
29 import org.eclipse.ui.navigator.IMementoAware;
30 import org.eclipse.ui.navigator.IPipelinedTreeContentProvider;
31 import org.eclipse.ui.navigator.IPipelinedTreeContentProvider2;
32 import org.eclipse.ui.navigator.PipelinedShapeModification;
33 import org.eclipse.ui.navigator.PipelinedViewerUpdate;
34 
35 /**
36  * @since 3.2
37  */
38 public class SafeDelegateTreeContentProvider implements
39 		IPipelinedTreeContentProvider2, ITreePathContentProvider {
40 
41 	private static final TreePath[] NO_PATHS = new TreePath[0];
42 
43 	private final ITreeContentProvider contentProvider;
44 
45 	private StructuredViewer viewer;
46 
SafeDelegateTreeContentProvider(ITreeContentProvider aContentProvider)47 	SafeDelegateTreeContentProvider(ITreeContentProvider aContentProvider) {
48 		super();
49 		contentProvider = aContentProvider;
50 	}
51 
52 	/**
53 	 * @return true if the underlying content provider implements IPipelinedTreeContentProvider
54 	 */
isPipelined()55 	public boolean isPipelined() {
56 		return contentProvider instanceof IPipelinedTreeContentProvider;
57 	}
58 
59 	/**
60 	 * @return true if the underlying content provider implements IPipelinedTreeContentProviderHasChildren
61 	 */
isPipelinedHasChildren()62 	public boolean isPipelinedHasChildren() {
63 		return contentProvider instanceof IPipelinedTreeContentProvider2;
64 	}
65 
66 	/**
67 	 * @return true if the underlying content provider implements ITreePathContentProvider
68 	 */
isTreePath()69 	public boolean isTreePath() {
70 		return contentProvider instanceof ITreePathContentProvider;
71 	}
72 
73 	/**
74 	 *
75 	 */
76 	@Override
dispose()77 	public void dispose() {
78 		SafeRunner.run(new NavigatorSafeRunnable() {
79 			@Override
80 			public void run() throws Exception {
81 				contentProvider.dispose();
82 			}
83 		});
84 
85 	}
86 
87 	@Override
equals(Object anObject)88 	public boolean equals(Object anObject) {
89 		return contentProvider.equals(anObject);
90 	}
91 
92 	@Override
getChildren(Object aParentElement)93 	public Object[] getChildren(Object aParentElement) {
94 		if (aParentElement instanceof TreePath) {
95 			TreePath tp = (TreePath) aParentElement;
96 			return getChildren(tp);
97 		}
98 		return contentProvider.getChildren(aParentElement);
99 	}
100 
101 	@Override
getElements(Object anInputElement)102 	public Object[] getElements(Object anInputElement) {
103 		return contentProvider.getElements(anInputElement);
104 	}
105 
106 	@Override
getParent(Object anElement)107 	public Object getParent(Object anElement) {
108 		return contentProvider.getParent(anElement);
109 	}
110 
111 	@Override
hasChildren(Object anElement)112 	public boolean hasChildren(Object anElement) {
113 		return contentProvider.hasChildren(anElement);
114 	}
115 
116 	@Override
hashCode()117 	public int hashCode() {
118 		return contentProvider.hashCode();
119 	}
120 
121 	@Override
inputChanged(final Viewer aViewer, final Object anOldInput, final Object aNewInput)122 	public void inputChanged(final Viewer aViewer, final Object anOldInput, final Object aNewInput) {
123 		viewer = (StructuredViewer) aViewer;
124 
125 		SafeRunner.run(new NavigatorSafeRunnable() {
126 			@Override
127 			public void run() throws Exception {
128 				contentProvider.inputChanged(aViewer, anOldInput, aNewInput);
129 			}
130 		});
131 	}
132 
133 	@Override
toString()134 	public String toString() {
135 		return contentProvider.toString();
136 	}
137 
138 	/**
139 	 *
140 	 * @return The real content provider.
141 	 */
getDelegateContentProvider()142 	public ITreeContentProvider getDelegateContentProvider() {
143 		return contentProvider;
144 	}
145 
146 	@Override
restoreState(IMemento aMemento)147 	public void restoreState(IMemento aMemento) {
148 		if (contentProvider != null && contentProvider instanceof IMementoAware) {
149 			((IMementoAware) contentProvider).restoreState(aMemento);
150 		}
151 
152 	}
153 
154 	@Override
saveState(IMemento aMemento)155 	public void saveState(IMemento aMemento) {
156 		if (contentProvider != null && contentProvider instanceof IMementoAware) {
157 			((IMementoAware) contentProvider).saveState(aMemento);
158 		}
159 
160 	}
161 
162 	@Override
init(ICommonContentExtensionSite aConfig)163 	public void init(ICommonContentExtensionSite aConfig) {
164 		if (contentProvider instanceof ICommonContentProvider) {
165 			((ICommonContentProvider) contentProvider).init(aConfig);
166 		}
167 	}
168 
169 	@Override
getPipelinedChildren(Object aParent, Set theCurrentChildren)170 	public void getPipelinedChildren(Object aParent, Set theCurrentChildren) {
171 		if (contentProvider instanceof IPipelinedTreeContentProvider) {
172 			((IPipelinedTreeContentProvider) contentProvider)
173 					.getPipelinedChildren(aParent, theCurrentChildren);
174 		}
175 
176 	}
177 
178 	@Override
getPipelinedElements(Object anInput, Set theCurrentElements)179 	public void getPipelinedElements(Object anInput, Set theCurrentElements) {
180 		if (contentProvider instanceof IPipelinedTreeContentProvider) {
181 			((IPipelinedTreeContentProvider) contentProvider)
182 					.getPipelinedElements(anInput, theCurrentElements);
183 		}
184 	}
185 
186 	@Override
getPipelinedParent(Object anObject, Object aSuggestedParent)187 	public Object getPipelinedParent(Object anObject, Object aSuggestedParent) {
188 		if (contentProvider instanceof IPipelinedTreeContentProvider) {
189 			return ((IPipelinedTreeContentProvider) contentProvider)
190 					.getPipelinedParent(anObject, aSuggestedParent);
191 		}
192 		return anObject;
193 	}
194 
195 	@Override
interceptAdd( PipelinedShapeModification anAddModification)196 	public PipelinedShapeModification interceptAdd(
197 			PipelinedShapeModification anAddModification) {
198 		if (contentProvider instanceof IPipelinedTreeContentProvider) {
199 			return ((IPipelinedTreeContentProvider) contentProvider)
200 					.interceptAdd(anAddModification);
201 		}
202 		return anAddModification;
203 	}
204 
205 	@Override
interceptRemove( PipelinedShapeModification aRemoveModification)206 	public PipelinedShapeModification interceptRemove(
207 			PipelinedShapeModification aRemoveModification) {
208 		if (contentProvider instanceof IPipelinedTreeContentProvider) {
209 			return ((IPipelinedTreeContentProvider) contentProvider)
210 					.interceptRemove(aRemoveModification);
211 		}
212 		return aRemoveModification;
213 	}
214 
215 	@Override
interceptRefresh( PipelinedViewerUpdate aRefreshSynchronization)216 	public boolean interceptRefresh(
217 			PipelinedViewerUpdate aRefreshSynchronization) {
218 		if (contentProvider instanceof IPipelinedTreeContentProvider) {
219 			return ((IPipelinedTreeContentProvider) contentProvider)
220 					.interceptRefresh(aRefreshSynchronization);
221 		}
222 		return false;
223 	}
224 
225 	@Override
interceptUpdate( PipelinedViewerUpdate anUpdateSynchronization)226 	public boolean interceptUpdate(
227 			PipelinedViewerUpdate anUpdateSynchronization) {
228 		if (contentProvider instanceof IPipelinedTreeContentProvider) {
229 			return ((IPipelinedTreeContentProvider) contentProvider)
230 					.interceptUpdate(anUpdateSynchronization);
231 		}
232 		return false;
233 	}
234 
235 	@Override
getChildren(TreePath parentPath)236 	public Object[] getChildren(TreePath parentPath) {
237 		if (contentProvider instanceof ITreePathContentProvider) {
238 			ITreePathContentProvider tpcp = (ITreePathContentProvider) contentProvider;
239 			return tpcp.getChildren(parentPath);
240 		}
241 		return getChildren(parentPath.getLastSegment());
242 	}
243 
244 	@Override
hasChildren(TreePath path)245 	public boolean hasChildren(TreePath path) {
246 		if (contentProvider instanceof ITreePathContentProvider) {
247 			ITreePathContentProvider tpcp = (ITreePathContentProvider) contentProvider;
248 			return tpcp.hasChildren(path);
249 		}
250 		return hasChildren(path.getLastSegment());
251 	}
252 
253 	@Override
getParents(Object element)254 	public TreePath[] getParents(Object element) {
255 		if (contentProvider instanceof ITreePathContentProvider) {
256 			ITreePathContentProvider tpcp = (ITreePathContentProvider) contentProvider;
257 			return tpcp.getParents(element);
258 		}
259 		ArrayList segments = new ArrayList();
260 		Object parent = element;
261 		do {
262 			parent = contentProvider.getParent(parent);
263 			if (parent != null && parent != viewer.getInput())
264 				segments.add(0, parent);
265 		} while (parent != null && parent != viewer.getInput());
266 		if (!segments.isEmpty()) {
267 			// Loop backwards over the array to create the path.
268 			return new TreePath[] { new TreePath(segments.toArray()) };
269 		}
270 		return NO_PATHS;
271 	}
272 
273 	@Override
hasPipelinedChildren(Object anInput, boolean currentHasChildren)274 	public boolean hasPipelinedChildren(Object anInput, boolean currentHasChildren) {
275 		if (contentProvider instanceof IPipelinedTreeContentProvider2) {
276 			return ((IPipelinedTreeContentProvider2) contentProvider)
277 					.hasPipelinedChildren(anInput, currentHasChildren);
278 		}
279 		return currentHasChildren;
280 	}
281 
282 }
283