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