]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java
Introduce E4 privileged job
[lgpl/argeo-commons.git] / org.argeo.cms.e4 / src / org / argeo / cms / e4 / 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.cms.e4.jcr;
17
18 import java.util.List;
19
20 import javax.annotation.PostConstruct;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.jcr.Property;
24 import javax.jcr.PropertyType;
25 import javax.jcr.Repository;
26 import javax.jcr.RepositoryException;
27 import javax.jcr.RepositoryFactory;
28 import javax.jcr.Session;
29 import javax.jcr.Value;
30 import javax.jcr.observation.Event;
31 import javax.jcr.observation.EventListener;
32 import javax.jcr.observation.ObservationManager;
33
34 import org.argeo.cms.CmsException;
35 import org.argeo.cms.ui.jcr.JcrBrowserUtils;
36 import org.argeo.cms.ui.jcr.NodeContentProvider;
37 import org.argeo.cms.ui.jcr.NodeLabelProvider;
38 import org.argeo.cms.ui.jcr.OsgiRepositoryRegister;
39 import org.argeo.cms.ui.jcr.PropertiesContentProvider;
40 import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
41 import org.argeo.cms.util.CmsUtils;
42 import org.argeo.eclipse.ui.EclipseUiException;
43 import org.argeo.eclipse.ui.TreeParent;
44 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
45 import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
46 import org.argeo.node.security.CryptoKeyring;
47 import org.eclipse.e4.core.contexts.IEclipseContext;
48 import org.eclipse.e4.ui.services.EMenuService;
49 import org.eclipse.e4.ui.workbench.modeling.EPartService;
50 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
51 import org.eclipse.jface.viewers.ColumnLabelProvider;
52 import org.eclipse.jface.viewers.IBaseLabelProvider;
53 import org.eclipse.jface.viewers.ISelectionChangedListener;
54 import org.eclipse.jface.viewers.IStructuredSelection;
55 import org.eclipse.jface.viewers.ITreeContentProvider;
56 import org.eclipse.jface.viewers.SelectionChangedEvent;
57 import org.eclipse.jface.viewers.StructuredSelection;
58 import org.eclipse.jface.viewers.TableViewer;
59 import org.eclipse.jface.viewers.TableViewerColumn;
60 import org.eclipse.jface.viewers.TreeViewer;
61 import org.eclipse.swt.SWT;
62 import org.eclipse.swt.custom.SashForm;
63 import org.eclipse.swt.layout.FillLayout;
64 import org.eclipse.swt.layout.GridData;
65 import org.eclipse.swt.widgets.Composite;
66 import org.eclipse.swt.widgets.Display;
67
68 /**
69 * Basic View to display a sash form to browse a JCR compliant multiple
70 * repository environment
71 */
72 public class JcrBrowserView {
73 final static String ID = "org.argeo.cms.e4.jcrbrowser";
74 final static String NODE_VIEWER_POPUP_MENU_ID = "org.argeo.cms.e4.popupmenu.nodeViewer";
75
76 private boolean sortChildNodes = true;
77
78 /* DEPENDENCY INJECTION */
79 private CryptoKeyring keyring;
80 @Inject
81 private RepositoryFactory repositoryFactory;
82 @Inject
83 private Repository nodeRepository;
84
85 // Current user session on the home repository default workspace
86 private Session userSession;
87
88 private OsgiRepositoryRegister repositoryRegister = new OsgiRepositoryRegister();
89
90 // This page widgets
91 private TreeViewer nodesViewer;
92 private NodeContentProvider nodeContentProvider;
93 private TableViewer propertiesViewer;
94 private EventListener resultsObserver;
95
96 @PostConstruct
97 public void createPartControl(Composite parent, IEclipseContext context, EPartService partService,
98 ESelectionService selectionService, EMenuService menuService) {
99 repositoryRegister.init();
100
101 parent.setLayout(new FillLayout());
102 SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
103 // sashForm.setSashWidth(4);
104 // sashForm.setLayout(new FillLayout());
105
106 // Create the tree on top of the view
107 Composite top = new Composite(sashForm, SWT.NONE);
108 // GridLayout gl = new GridLayout(1, false);
109 top.setLayout(CmsUtils.noSpaceGridLayout());
110
111 try {
112 this.userSession = this.nodeRepository.login();
113 } catch (RepositoryException e) {
114 throw new CmsException("Cannot open user session", e);
115 }
116
117 nodeContentProvider = new NodeContentProvider(userSession, keyring, repositoryRegister, repositoryFactory,
118 sortChildNodes);
119
120 // nodes viewer
121 nodesViewer = createNodeViewer(top, nodeContentProvider);
122
123 // context menu : it is completely defined in the plugin.xml file.
124 // MenuManager menuManager = new MenuManager();
125 // Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
126
127 // nodesViewer.getTree().setMenu(menu);
128
129 nodesViewer.setInput("");
130
131 // Create the property viewer on the bottom
132 Composite bottom = new Composite(sashForm, SWT.NONE);
133 bottom.setLayout(CmsUtils.noSpaceGridLayout());
134 propertiesViewer = createPropertiesViewer(bottom);
135
136 sashForm.setWeights(getWeights());
137 nodesViewer.setComparer(new NodeViewerComparer());
138 nodesViewer.addSelectionChangedListener(new ISelectionChangedListener() {
139 public void selectionChanged(SelectionChangedEvent event) {
140 IStructuredSelection selection = (IStructuredSelection) event.getSelection();
141 selectionService.setSelection(selection.toList());
142 }
143 });
144 nodesViewer.addDoubleClickListener(new JcrE4DClickListener(nodesViewer, partService));
145 menuService.registerContextMenu(nodesViewer.getControl(), NODE_VIEWER_POPUP_MENU_ID);
146 // getSite().registerContextMenu(menuManager, nodesViewer);
147 // getSite().setSelectionProvider(nodesViewer);
148 }
149
150 @PreDestroy
151 public void dispose() {
152 repositoryRegister.destroy();
153 }
154
155 public void refresh(Object obj) {
156 // Enable full refresh from a command when no element of the tree is
157 // selected
158 if (obj == null) {
159 Object[] elements = nodeContentProvider.getElements(null);
160 for (Object el : elements) {
161 if (el instanceof TreeParent)
162 JcrBrowserUtils.forceRefreshIfNeeded((TreeParent) el);
163 getNodeViewer().refresh(el);
164 }
165 } else
166 getNodeViewer().refresh(obj);
167 }
168
169 /**
170 * To be overridden to adapt size of form and result frames.
171 */
172 protected int[] getWeights() {
173 return new int[] { 70, 30 };
174 }
175
176 protected TreeViewer createNodeViewer(Composite parent, final ITreeContentProvider nodeContentProvider) {
177
178 final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
179
180 tmpNodeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
181
182 tmpNodeViewer.setContentProvider(nodeContentProvider);
183 tmpNodeViewer.setLabelProvider((IBaseLabelProvider) new NodeLabelProvider());
184 tmpNodeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
185 public void selectionChanged(SelectionChangedEvent event) {
186 if (!event.getSelection().isEmpty()) {
187 IStructuredSelection sel = (IStructuredSelection) event.getSelection();
188 Object firstItem = sel.getFirstElement();
189 if (firstItem instanceof SingleJcrNodeElem)
190 propertiesViewer.setInput(((SingleJcrNodeElem) firstItem).getNode());
191 } else {
192 propertiesViewer.setInput("");
193 }
194 }
195 });
196
197 resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay());
198 if (keyring != null)
199 try {
200 ObservationManager observationManager = userSession.getWorkspace().getObservationManager();
201 observationManager.addEventListener(resultsObserver, Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/",
202 true, null, null, false);
203 } catch (RepositoryException e) {
204 throw new EclipseUiException("Cannot register listeners", e);
205 }
206
207 // tmpNodeViewer.addDoubleClickListener(new JcrDClickListener(tmpNodeViewer));
208 return tmpNodeViewer;
209 }
210
211 protected TableViewer createPropertiesViewer(Composite parent) {
212 propertiesViewer = new TableViewer(parent, SWT.NONE);
213 propertiesViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
214 propertiesViewer.getTable().setHeaderVisible(true);
215 propertiesViewer.setContentProvider(new PropertiesContentProvider());
216 TableViewerColumn col = new TableViewerColumn(propertiesViewer, SWT.NONE);
217 col.getColumn().setText("Name");
218 col.getColumn().setWidth(200);
219 col.setLabelProvider(new ColumnLabelProvider() {
220 private static final long serialVersionUID = -6684361063107478595L;
221
222 public String getText(Object element) {
223 try {
224 return ((Property) element).getName();
225 } catch (RepositoryException e) {
226 throw new EclipseUiException("Unexpected exception in label provider", e);
227 }
228 }
229 });
230 col = new TableViewerColumn(propertiesViewer, SWT.NONE);
231 col.getColumn().setText("Value");
232 col.getColumn().setWidth(400);
233 col.setLabelProvider(new ColumnLabelProvider() {
234 private static final long serialVersionUID = -8201994187693336657L;
235
236 public String getText(Object element) {
237 try {
238 Property property = (Property) element;
239 if (property.getType() == PropertyType.BINARY)
240 return "<binary>";
241 else if (property.isMultiple()) {
242 StringBuffer buf = new StringBuffer("[");
243 Value[] values = property.getValues();
244 for (int i = 0; i < values.length; i++) {
245 if (i != 0)
246 buf.append(", ");
247 buf.append(values[i].getString());
248 }
249 buf.append(']');
250 return buf.toString();
251 } else
252 return property.getValue().getString();
253 } catch (RepositoryException e) {
254 throw new EclipseUiException("Unexpected exception in label provider", e);
255 }
256 }
257 });
258 col = new TableViewerColumn(propertiesViewer, SWT.NONE);
259 col.getColumn().setText("Type");
260 col.getColumn().setWidth(200);
261 col.setLabelProvider(new ColumnLabelProvider() {
262 private static final long serialVersionUID = -6009599998150286070L;
263
264 public String getText(Object element) {
265 return JcrBrowserUtils.getPropertyTypeAsString((Property) element);
266 }
267 });
268 propertiesViewer.setInput("");
269 return propertiesViewer;
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()).setSortChildren(sortChildNodes);
286 nodesViewer.setInput("");
287 }
288
289 /** Notifies the current view that a node has been added */
290 public void nodeAdded(TreeParent parentNode) {
291 // insure that Ui objects have been correctly created:
292 JcrBrowserUtils.forceRefreshIfNeeded(parentNode);
293 getNodeViewer().refresh(parentNode);
294 getNodeViewer().expandToLevel(parentNode, 1);
295 }
296
297 /** Notifies the current view that a node has been removed */
298 public void nodeRemoved(TreeParent parentNode) {
299 IStructuredSelection newSel = new StructuredSelection(parentNode);
300 getNodeViewer().setSelection(newSel, true);
301 // Force refresh
302 IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer().getSelection();
303 getNodeViewer().refresh(tmpSel.getFirstElement());
304 }
305
306 class TreeObserver extends AsyncUiEventListener {
307
308 public TreeObserver(Display display) {
309 super(display);
310 }
311
312 @Override
313 protected Boolean willProcessInUiThread(List<Event> events) throws RepositoryException {
314 for (Event event : events) {
315 if (getLog().isTraceEnabled())
316 getLog().debug("Received event " + event);
317 String path = event.getPath();
318 int index = path.lastIndexOf('/');
319 String propertyName = path.substring(index + 1);
320 if (getLog().isTraceEnabled())
321 getLog().debug("Concerned property " + propertyName);
322 }
323 return false;
324 }
325
326 protected void onEventInUiThread(List<Event> events) throws RepositoryException {
327 if (getLog().isTraceEnabled())
328 getLog().trace("Refresh result list");
329 nodesViewer.refresh();
330 }
331
332 }
333
334 public boolean getSortChildNodes() {
335 return sortChildNodes;
336 }
337
338 public void setFocus() {
339 getNodeViewer().getTree().setFocus();
340 }
341
342 /* DEPENDENCY INJECTION */
343 // public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
344 // this.repositoryRegister = repositoryRegister;
345 // }
346
347 public void setKeyring(CryptoKeyring 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 }