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