]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java
fix bug 85 : JCR explorer refresh was not implemented for TreeParent objects of type...
[lgpl/argeo-commons.git] / server / plugins / org.argeo.jcr.ui.explorer / src / main / java / org / argeo / jcr / ui / explorer / views / GenericJcrBrowser.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
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.RepositoryException;
23 import javax.jcr.RepositoryFactory;
24 import javax.jcr.Value;
25 import javax.jcr.observation.Event;
26 import javax.jcr.observation.EventListener;
27 import javax.jcr.observation.ObservationManager;
28
29 import org.argeo.ArgeoException;
30 import org.argeo.eclipse.ui.TreeParent;
31 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
32 import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
33 import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser;
34 import org.argeo.jcr.RepositoryRegister;
35 import org.argeo.jcr.security.JcrKeyring;
36 import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
37 import org.argeo.jcr.ui.explorer.browser.NodeContentProvider;
38 import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider;
39 import org.argeo.jcr.ui.explorer.browser.PropertiesContentProvider;
40 import org.argeo.jcr.ui.explorer.model.SingleJcrNode;
41 import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
42 import org.argeo.jcr.ui.explorer.utils.JcrUiUtils;
43 import org.eclipse.jface.action.MenuManager;
44 import org.eclipse.jface.viewers.ColumnLabelProvider;
45 import org.eclipse.jface.viewers.ISelectionChangedListener;
46 import org.eclipse.jface.viewers.IStructuredSelection;
47 import org.eclipse.jface.viewers.ITreeContentProvider;
48 import org.eclipse.jface.viewers.SelectionChangedEvent;
49 import org.eclipse.jface.viewers.StructuredSelection;
50 import org.eclipse.jface.viewers.TableViewer;
51 import org.eclipse.jface.viewers.TableViewerColumn;
52 import org.eclipse.jface.viewers.TreeViewer;
53 import org.eclipse.swt.SWT;
54 import org.eclipse.swt.custom.SashForm;
55 import org.eclipse.swt.layout.FillLayout;
56 import org.eclipse.swt.layout.GridData;
57 import org.eclipse.swt.layout.GridLayout;
58 import org.eclipse.swt.widgets.Composite;
59 import org.eclipse.swt.widgets.Display;
60 import org.eclipse.swt.widgets.Menu;
61
62 /**
63 * Basic View to display a sash form to browse a JCR compliant multirepository
64 * environment
65 */
66
67 public class GenericJcrBrowser extends AbstractJcrBrowser {
68 // private final static Log log =
69 // LogFactory.getLog(GenericJcrBrowser.class);
70 public final static String ID = JcrExplorerPlugin.ID + ".browserView";
71 private boolean sortChildNodes = false;
72
73 /* DEPENDENCY INJECTION */
74 private JcrKeyring jcrKeyring;
75 private RepositoryRegister repositoryRegister;
76 private RepositoryFactory repositoryFactory;
77
78 // This page widgets
79 private TreeViewer nodesViewer;
80 private NodeContentProvider nodeContentProvider;
81 private TableViewer propertiesViewer;
82 private EventListener resultsObserver;
83
84 // Manage documents
85 // private JcrFileProvider jcrFileProvider;
86 // private FileHandler fileHandler;
87
88 @Override
89 public void createPartControl(Composite parent) {
90
91 // look for session
92 // Session nodeSession = jcrKeyring != null ? jcrKeyring.getSession()
93 // : null;
94 // if (nodeSession == null) {
95 // Repository nodeRepository = JcrUtils.getRepositoryByAlias(
96 // repositoryRegister, ArgeoJcrConstants.ALIAS_NODE);
97 // if (nodeRepository != null)
98 // try {
99 // nodeSession = nodeRepository.login();
100 // // TODO : enhance that to enable multirepository listener.
101 // } catch (RepositoryException e1) {
102 // throw new ArgeoException("Cannot login to node repository");
103 // }
104 // }
105
106 // Instantiate the generic object that fits for
107 // both RCP & RAP
108 // Note that in RAP, it registers a service handler that provide the
109 // access to the files.
110 // jcrFileProvider = new JcrFileProvider();
111 // fileHandler = new FileHandler(jcrFileProvider);
112
113 parent.setLayout(new FillLayout());
114 SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
115 sashForm.setSashWidth(4);
116 sashForm.setLayout(new FillLayout());
117
118 // Create the tree on top of the view
119 Composite top = new Composite(sashForm, SWT.NONE);
120 GridLayout gl = new GridLayout(1, false);
121 top.setLayout(gl);
122
123 nodeContentProvider = new NodeContentProvider(jcrKeyring,
124 repositoryRegister, repositoryFactory, sortChildNodes);
125
126 // nodes viewer
127 nodesViewer = createNodeViewer(top, nodeContentProvider);
128
129 // context menu : it is completely defined in the plugin.xml file.
130 MenuManager menuManager = new MenuManager();
131 Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
132
133 nodesViewer.getTree().setMenu(menu);
134 getSite().registerContextMenu(menuManager, nodesViewer);
135 getSite().setSelectionProvider(nodesViewer);
136
137 nodesViewer.setInput(getViewSite());
138
139 // Create the property viewer on the bottom
140 Composite bottom = new Composite(sashForm, SWT.NONE);
141 bottom.setLayout(new GridLayout(1, false));
142 propertiesViewer = createPropertiesViewer(bottom);
143
144 sashForm.setWeights(getWeights());
145 nodesViewer.setComparer(new NodeViewerComparer());
146 }
147
148 /**
149 * To be overridden to adapt size of form and result frames.
150 */
151 protected int[] getWeights() {
152 return new int[] { 70, 30 };
153 }
154
155 protected TreeViewer createNodeViewer(Composite parent,
156 final ITreeContentProvider nodeContentProvider) {
157
158 final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
159
160 tmpNodeViewer.getTree().setLayoutData(
161 new GridData(SWT.FILL, SWT.FILL, true, true));
162
163 tmpNodeViewer.setContentProvider(nodeContentProvider);
164 tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
165 tmpNodeViewer
166 .addSelectionChangedListener(new ISelectionChangedListener() {
167 public void selectionChanged(SelectionChangedEvent event) {
168 if (!event.getSelection().isEmpty()) {
169 IStructuredSelection sel = (IStructuredSelection) event
170 .getSelection();
171 Object firstItem = sel.getFirstElement();
172 if (firstItem instanceof SingleJcrNode)
173 propertiesViewer
174 .setInput(((SingleJcrNode) firstItem)
175 .getNode());
176 } else {
177 propertiesViewer.setInput(getViewSite());
178 }
179 }
180 });
181
182 resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay());
183 if (jcrKeyring != null)
184 try {
185 ObservationManager observationManager = jcrKeyring.getSession()
186 .getWorkspace().getObservationManager();
187 observationManager.addEventListener(resultsObserver,
188 Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/",
189 true, null, null, false);
190 } catch (RepositoryException e) {
191 throw new ArgeoException("Cannot register listeners", e);
192 }
193
194 tmpNodeViewer
195 .addDoubleClickListener(new GenericNodeDoubleClickListener(
196 tmpNodeViewer));
197 return tmpNodeViewer;
198 }
199
200 protected TableViewer createPropertiesViewer(Composite parent) {
201 propertiesViewer = new TableViewer(parent);
202 propertiesViewer.getTable().setLayoutData(
203 new GridData(SWT.FILL, SWT.FILL, true, true));
204 propertiesViewer.getTable().setHeaderVisible(true);
205 propertiesViewer.setContentProvider(new PropertiesContentProvider());
206 TableViewerColumn col = new TableViewerColumn(propertiesViewer,
207 SWT.NONE);
208 col.getColumn().setText("Name");
209 col.getColumn().setWidth(200);
210 col.setLabelProvider(new ColumnLabelProvider() {
211 public String getText(Object element) {
212 try {
213 return ((Property) element).getName();
214 } catch (RepositoryException e) {
215 throw new ArgeoException(
216 "Unexpected exception in label provider", e);
217 }
218 }
219 });
220 col = new TableViewerColumn(propertiesViewer, SWT.NONE);
221 col.getColumn().setText("Value");
222 col.getColumn().setWidth(400);
223 col.setLabelProvider(new ColumnLabelProvider() {
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 public String getText(Object element) {
252 try {
253 return PropertyType.nameFromValue(((Property) element)
254 .getType());
255 } catch (RepositoryException e) {
256 throw new ArgeoException(
257 "Unexpected exception in label provider", e);
258 }
259 }
260 });
261 propertiesViewer.setInput(getViewSite());
262 return propertiesViewer;
263 }
264
265 @Override
266 public void dispose() {
267 super.dispose();
268 }
269
270 @Override
271 protected TreeViewer getNodeViewer() {
272 return nodesViewer;
273 }
274
275 /** Notifies the current view that a node has been added */
276 public void nodeAdded(TreeParent parentNode) {
277 // insure that Ui objects have been correctly created:
278 JcrUiUtils.forceRefreshIfNeeded(parentNode);
279 getNodeViewer().refresh(parentNode);
280 getNodeViewer().expandToLevel(parentNode, 1);
281 }
282
283 /** Notifies the current view that a node has been added */
284 public void nodeRemoved(TreeParent parentNode) {
285 IStructuredSelection newSel = new StructuredSelection(parentNode);
286 getNodeViewer().setSelection(newSel, true);
287 // Force refresh
288 IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer()
289 .getSelection();
290 getNodeViewer().refresh(tmpSel.getFirstElement());
291 }
292
293 class TreeObserver extends AsyncUiEventListener {
294
295 public TreeObserver(Display display) {
296 super(display);
297 }
298
299 @Override
300 protected Boolean willProcessInUiThread(List<Event> events)
301 throws RepositoryException {
302 for (Event event : events) {
303 if (getLog().isTraceEnabled())
304 getLog().debug("Received event " + event);
305 String path = event.getPath();
306 int index = path.lastIndexOf('/');
307 String propertyName = path.substring(index + 1);
308 if (getLog().isTraceEnabled())
309 getLog().debug("Concerned property " + propertyName);
310 }
311 return false;
312 }
313
314 protected void onEventInUiThread(List<Event> events)
315 throws RepositoryException {
316 if (getLog().isTraceEnabled())
317 getLog().trace("Refresh result list");
318 nodesViewer.refresh();
319 }
320
321 }
322
323 public void setSortChildNodes(boolean sortChildNodes) {
324 this.sortChildNodes = sortChildNodes;
325 }
326
327 public boolean getSortChildNodes() {
328 return sortChildNodes;
329 }
330
331 /* DEPENDENCY INJECTION */
332 public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
333 this.repositoryRegister = repositoryRegister;
334 }
335
336 public void setJcrKeyring(JcrKeyring jcrKeyring) {
337 this.jcrKeyring = jcrKeyring;
338 }
339
340 public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
341 this.repositoryFactory = repositoryFactory;
342 }
343
344 }