]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/jcr/JcrBrowserView.java
Revert hack that was necessary before Rap 2.3.x
[lgpl/argeo-commons.git] / org.argeo.eclipse.ui.workbench / src / org / argeo / eclipse / ui / workbench / jcr / JcrBrowserView.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.eclipse.ui.workbench.jcr;
17
18 import java.util.List;
19
20 import javax.jcr.Property;
21 import javax.jcr.PropertyType;
22 import javax.jcr.Repository;
23 import javax.jcr.RepositoryException;
24 import javax.jcr.RepositoryFactory;
25 import javax.jcr.Session;
26 import javax.jcr.Value;
27 import javax.jcr.observation.Event;
28 import javax.jcr.observation.EventListener;
29 import javax.jcr.observation.ObservationManager;
30
31 import org.argeo.ArgeoException;
32 import org.argeo.eclipse.ui.TreeParent;
33 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
34 import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
35 import org.argeo.eclipse.ui.workbench.WorkbenchUiPlugin;
36 import org.argeo.eclipse.ui.workbench.jcr.internal.GenericNodeDoubleClickListener;
37 import org.argeo.eclipse.ui.workbench.jcr.internal.JcrBrowserUtils;
38 import org.argeo.eclipse.ui.workbench.jcr.internal.NodeContentProvider;
39 import org.argeo.eclipse.ui.workbench.jcr.internal.NodeLabelProvider;
40 import org.argeo.eclipse.ui.workbench.jcr.internal.PropertiesContentProvider;
41 import org.argeo.eclipse.ui.workbench.jcr.internal.model.SingleJcrNodeElem;
42 import org.argeo.jcr.RepositoryRegister;
43 import org.argeo.util.security.Keyring;
44 import org.eclipse.jface.action.MenuManager;
45 import org.eclipse.jface.viewers.ColumnLabelProvider;
46 import org.eclipse.jface.viewers.ISelectionChangedListener;
47 import org.eclipse.jface.viewers.IStructuredSelection;
48 import org.eclipse.jface.viewers.ITreeContentProvider;
49 import org.eclipse.jface.viewers.SelectionChangedEvent;
50 import org.eclipse.jface.viewers.StructuredSelection;
51 import org.eclipse.jface.viewers.TableViewer;
52 import org.eclipse.jface.viewers.TableViewerColumn;
53 import org.eclipse.jface.viewers.TreeViewer;
54 import org.eclipse.swt.SWT;
55 import org.eclipse.swt.custom.SashForm;
56 import org.eclipse.swt.layout.FillLayout;
57 import org.eclipse.swt.layout.GridData;
58 import org.eclipse.swt.layout.GridLayout;
59 import org.eclipse.swt.widgets.Composite;
60 import org.eclipse.swt.widgets.Display;
61 import org.eclipse.swt.widgets.Menu;
62 import org.eclipse.ui.part.ViewPart;
63
64 /**
65 * Basic View to display a sash form to browse a JCR compliant multiple
66 * repository environment
67 */
68 public class JcrBrowserView extends ViewPart {
69 public final static String ID = WorkbenchUiPlugin.ID + ".jcrBrowserView";
70 private boolean sortChildNodes = true;
71
72 /* DEPENDENCY INJECTION */
73 private Keyring keyring;
74 private RepositoryRegister repositoryRegister;
75 private RepositoryFactory repositoryFactory;
76 private Repository nodeRepository;
77
78 // Current user session on the "Argeo node" default workspace
79 private Session userSession;
80
81 // This page widgets
82 private TreeViewer nodesViewer;
83 private NodeContentProvider nodeContentProvider;
84 private TableViewer propertiesViewer;
85 private EventListener resultsObserver;
86
87 @Override
88 public void createPartControl(Composite parent) {
89 parent.setLayout(new FillLayout());
90 SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
91 sashForm.setSashWidth(4);
92 sashForm.setLayout(new FillLayout());
93
94 // Create the tree on top of the view
95 Composite top = new Composite(sashForm, SWT.NONE);
96 GridLayout gl = new GridLayout(1, false);
97 top.setLayout(gl);
98
99 try {
100 this.userSession = this.nodeRepository.login();
101 } catch (RepositoryException e) {
102 throw new ArgeoException("Cannot open user session", e);
103 }
104
105 nodeContentProvider = new NodeContentProvider(userSession, keyring,
106 repositoryRegister, repositoryFactory, sortChildNodes);
107
108 // nodes viewer
109 nodesViewer = createNodeViewer(top, nodeContentProvider);
110
111 // context menu : it is completely defined in the plugin.xml file.
112 MenuManager menuManager = new MenuManager();
113 Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
114
115 nodesViewer.getTree().setMenu(menu);
116 getSite().registerContextMenu(menuManager, nodesViewer);
117 getSite().setSelectionProvider(nodesViewer);
118
119 nodesViewer.setInput(getViewSite());
120
121 // Create the property viewer on the bottom
122 Composite bottom = new Composite(sashForm, SWT.NONE);
123 bottom.setLayout(new GridLayout(1, false));
124 propertiesViewer = createPropertiesViewer(bottom);
125
126 sashForm.setWeights(getWeights());
127 nodesViewer.setComparer(new NodeViewerComparer());
128 }
129
130 public void refresh(Object obj) {
131 // Enable full refresh from a command when no element of the tree is
132 // selected
133 if (obj == null) {
134 Object[] elements = nodeContentProvider.getElements(null);
135 for (Object el : elements) {
136 if (el instanceof TreeParent)
137 JcrBrowserUtils.forceRefreshIfNeeded((TreeParent) el);
138 getNodeViewer().refresh(el);
139 }
140 } else
141 getNodeViewer().refresh(obj);
142 }
143
144 /**
145 * To be overridden to adapt size of form and result frames.
146 */
147 protected int[] getWeights() {
148 return new int[] { 70, 30 };
149 }
150
151 protected TreeViewer createNodeViewer(Composite parent,
152 final ITreeContentProvider nodeContentProvider) {
153
154 final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
155
156 tmpNodeViewer.getTree().setLayoutData(
157 new GridData(SWT.FILL, SWT.FILL, true, true));
158
159 tmpNodeViewer.setContentProvider(nodeContentProvider);
160 tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
161 tmpNodeViewer
162 .addSelectionChangedListener(new ISelectionChangedListener() {
163 public void selectionChanged(SelectionChangedEvent event) {
164 if (!event.getSelection().isEmpty()) {
165 IStructuredSelection sel = (IStructuredSelection) event
166 .getSelection();
167 Object firstItem = sel.getFirstElement();
168 if (firstItem instanceof SingleJcrNodeElem)
169 propertiesViewer
170 .setInput(((SingleJcrNodeElem) firstItem)
171 .getNode());
172 } else {
173 propertiesViewer.setInput(getViewSite());
174 }
175 }
176 });
177
178 resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay());
179 if (keyring != null)
180 try {
181 ObservationManager observationManager = userSession
182 .getWorkspace().getObservationManager();
183 observationManager.addEventListener(resultsObserver,
184 Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/",
185 true, null, null, false);
186 } catch (RepositoryException e) {
187 throw new ArgeoException("Cannot register listeners", e);
188 }
189
190 tmpNodeViewer
191 .addDoubleClickListener(new GenericNodeDoubleClickListener(
192 tmpNodeViewer));
193 return tmpNodeViewer;
194 }
195
196 protected TableViewer createPropertiesViewer(Composite parent) {
197 propertiesViewer = new TableViewer(parent);
198 propertiesViewer.getTable().setLayoutData(
199 new GridData(SWT.FILL, SWT.FILL, true, true));
200 propertiesViewer.getTable().setHeaderVisible(true);
201 propertiesViewer.setContentProvider(new PropertiesContentProvider());
202 TableViewerColumn col = new TableViewerColumn(propertiesViewer,
203 SWT.NONE);
204 col.getColumn().setText("Name");
205 col.getColumn().setWidth(200);
206 col.setLabelProvider(new ColumnLabelProvider() {
207 private static final long serialVersionUID = -6684361063107478595L;
208
209 public String getText(Object element) {
210 try {
211 return ((Property) element).getName();
212 } catch (RepositoryException e) {
213 throw new ArgeoException(
214 "Unexpected exception in label provider", e);
215 }
216 }
217 });
218 col = new TableViewerColumn(propertiesViewer, SWT.NONE);
219 col.getColumn().setText("Value");
220 col.getColumn().setWidth(400);
221 col.setLabelProvider(new ColumnLabelProvider() {
222 private static final long serialVersionUID = -8201994187693336657L;
223
224 public String getText(Object element) {
225 try {
226 Property property = (Property) element;
227 if (property.getType() == PropertyType.BINARY)
228 return "<binary>";
229 else if (property.isMultiple()) {
230 StringBuffer buf = new StringBuffer("[");
231 Value[] values = property.getValues();
232 for (int i = 0; i < values.length; i++) {
233 if (i != 0)
234 buf.append(", ");
235 buf.append(values[i].getString());
236 }
237 buf.append(']');
238 return buf.toString();
239 } else
240 return property.getValue().getString();
241 } catch (RepositoryException e) {
242 throw new ArgeoException(
243 "Unexpected exception in label provider", e);
244 }
245 }
246 });
247 col = new TableViewerColumn(propertiesViewer, SWT.NONE);
248 col.getColumn().setText("Type");
249 col.getColumn().setWidth(200);
250 col.setLabelProvider(new ColumnLabelProvider() {
251 private static final long serialVersionUID = -6009599998150286070L;
252
253 public String getText(Object element) {
254 try {
255 return PropertyType.nameFromValue(((Property) element)
256 .getType());
257 } catch (RepositoryException e) {
258 throw new ArgeoException(
259 "Unexpected exception in label provider", e);
260 }
261 }
262 });
263 propertiesViewer.setInput(getViewSite());
264 return propertiesViewer;
265 }
266
267 @Override
268 public void dispose() {
269 super.dispose();
270 }
271
272 protected TreeViewer getNodeViewer() {
273 return nodesViewer;
274 }
275
276 /**
277 * Resets the tree content provider
278 *
279 * @param sortChildNodes
280 * if true the content provider will use a comparer to sort nodes
281 * that might slow down the display
282 * */
283 public void setSortChildNodes(boolean sortChildNodes) {
284 this.sortChildNodes = sortChildNodes;
285 ((NodeContentProvider) nodesViewer.getContentProvider())
286 .setSortChildren(sortChildNodes);
287 nodesViewer.setInput(getViewSite());
288 }
289
290 /** Notifies the current view that a node has been added */
291 public void nodeAdded(TreeParent parentNode) {
292 // insure that Ui objects have been correctly created:
293 JcrBrowserUtils.forceRefreshIfNeeded(parentNode);
294 getNodeViewer().refresh(parentNode);
295 getNodeViewer().expandToLevel(parentNode, 1);
296 }
297
298 /** Notifies the current view that a node has been removed */
299 public void nodeRemoved(TreeParent parentNode) {
300 IStructuredSelection newSel = new StructuredSelection(parentNode);
301 getNodeViewer().setSelection(newSel, true);
302 // Force refresh
303 IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer()
304 .getSelection();
305 getNodeViewer().refresh(tmpSel.getFirstElement());
306 }
307
308 class TreeObserver extends AsyncUiEventListener {
309
310 public TreeObserver(Display display) {
311 super(display);
312 }
313
314 @Override
315 protected Boolean willProcessInUiThread(List<Event> events)
316 throws RepositoryException {
317 for (Event event : events) {
318 if (getLog().isTraceEnabled())
319 getLog().debug("Received event " + event);
320 String path = event.getPath();
321 int index = path.lastIndexOf('/');
322 String propertyName = path.substring(index + 1);
323 if (getLog().isTraceEnabled())
324 getLog().debug("Concerned property " + propertyName);
325 }
326 return false;
327 }
328
329 protected void onEventInUiThread(List<Event> events)
330 throws RepositoryException {
331 if (getLog().isTraceEnabled())
332 getLog().trace("Refresh result list");
333 nodesViewer.refresh();
334 }
335
336 }
337
338 public boolean getSortChildNodes() {
339 return sortChildNodes;
340 }
341
342 /* DEPENDENCY INJECTION */
343 public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
344 this.repositoryRegister = repositoryRegister;
345 }
346
347 public void setKeyring(Keyring keyring) {
348 this.keyring = keyring;
349 }
350
351 public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
352 this.repositoryFactory = repositoryFactory;
353 }
354
355 public void setNodeRepository(Repository nodeRepository) {
356 this.nodeRepository = nodeRepository;
357 }
358
359 @Override
360 public void setFocus() {
361 getNodeViewer().getTree().setFocus();
362 }
363 }