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