2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.cms
.e4
.jcr
;
18 import java
.util
.List
;
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
;
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
;
69 * Basic View to display a sash form to browse a JCR compliant multiple
70 * repository environment
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";
76 private boolean sortChildNodes
= true;
78 /* DEPENDENCY INJECTION */
79 private CryptoKeyring keyring
;
81 private RepositoryFactory repositoryFactory
;
83 private Repository nodeRepository
;
85 // Current user session on the home repository default workspace
86 private Session userSession
;
88 private OsgiRepositoryRegister repositoryRegister
= new OsgiRepositoryRegister();
91 private TreeViewer nodesViewer
;
92 private NodeContentProvider nodeContentProvider
;
93 private TableViewer propertiesViewer
;
94 private EventListener resultsObserver
;
97 public void createPartControl(Composite parent
, IEclipseContext context
, EPartService partService
,
98 ESelectionService selectionService
, EMenuService menuService
) {
99 repositoryRegister
.init();
101 parent
.setLayout(new FillLayout());
102 SashForm sashForm
= new SashForm(parent
, SWT
.VERTICAL
);
103 // sashForm.setSashWidth(4);
104 // sashForm.setLayout(new FillLayout());
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());
112 this.userSession
= this.nodeRepository
.login();
113 } catch (RepositoryException e
) {
114 throw new CmsException("Cannot open user session", e
);
117 nodeContentProvider
= new NodeContentProvider(userSession
, keyring
, repositoryRegister
, repositoryFactory
,
121 nodesViewer
= createNodeViewer(top
, nodeContentProvider
);
123 // context menu : it is completely defined in the plugin.xml file.
124 // MenuManager menuManager = new MenuManager();
125 // Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
127 // nodesViewer.getTree().setMenu(menu);
129 nodesViewer
.setInput("");
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
);
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());
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);
151 public void dispose() {
152 repositoryRegister
.destroy();
155 public void refresh(Object obj
) {
156 // Enable full refresh from a command when no element of the tree is
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
);
166 getNodeViewer().refresh(obj
);
170 * To be overridden to adapt size of form and result frames.
172 protected int[] getWeights() {
173 return new int[] { 70, 30 };
176 protected TreeViewer
createNodeViewer(Composite parent
, final ITreeContentProvider nodeContentProvider
) {
178 final TreeViewer tmpNodeViewer
= new TreeViewer(parent
, SWT
.MULTI
);
180 tmpNodeViewer
.getTree().setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
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());
192 propertiesViewer
.setInput("");
197 resultsObserver
= new TreeObserver(tmpNodeViewer
.getTree().getDisplay());
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
);
207 // tmpNodeViewer.addDoubleClickListener(new JcrDClickListener(tmpNodeViewer));
208 return tmpNodeViewer
;
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;
222 public String
getText(Object element
) {
224 return ((Property
) element
).getName();
225 } catch (RepositoryException e
) {
226 throw new EclipseUiException("Unexpected exception in label provider", e
);
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;
236 public String
getText(Object element
) {
238 Property property
= (Property
) element
;
239 if (property
.getType() == PropertyType
.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
++) {
247 buf
.append(values
[i
].getString());
250 return buf
.toString();
252 return property
.getValue().getString();
253 } catch (RepositoryException e
) {
254 throw new EclipseUiException("Unexpected exception in label provider", e
);
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;
264 public String
getText(Object element
) {
265 return JcrBrowserUtils
.getPropertyTypeAsString((Property
) element
);
268 propertiesViewer
.setInput("");
269 return propertiesViewer
;
272 protected TreeViewer
getNodeViewer() {
277 * Resets the tree content provider
279 * @param sortChildNodes
280 * if true the content provider will use a comparer to sort nodes
281 * that might slow down the display
283 public void setSortChildNodes(boolean sortChildNodes
) {
284 this.sortChildNodes
= sortChildNodes
;
285 ((NodeContentProvider
) nodesViewer
.getContentProvider()).setSortChildren(sortChildNodes
);
286 nodesViewer
.setInput("");
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);
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);
302 IStructuredSelection tmpSel
= (IStructuredSelection
) getNodeViewer().getSelection();
303 getNodeViewer().refresh(tmpSel
.getFirstElement());
306 class TreeObserver
extends AsyncUiEventListener
{
308 public TreeObserver(Display display
) {
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
);
326 protected void onEventInUiThread(List
<Event
> events
) throws RepositoryException
{
327 if (getLog().isTraceEnabled())
328 getLog().trace("Refresh result list");
329 nodesViewer
.refresh();
334 public boolean getSortChildNodes() {
335 return sortChildNodes
;
338 public void setFocus() {
339 getNodeViewer().getTree().setFocus();
342 /* DEPENDENCY INJECTION */
343 // public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
344 // this.repositoryRegister = repositoryRegister;
347 public void setKeyring(CryptoKeyring keyring
) {
348 this.keyring
= keyring
;
351 public void setRepositoryFactory(RepositoryFactory repositoryFactory
) {
352 this.repositoryFactory
= repositoryFactory
;
355 public void setNodeRepository(Repository nodeRepository
) {
356 this.nodeRepository
= nodeRepository
;