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
.eclipse
.ui
.workbench
.jcr
;
18 import java
.util
.List
;
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
;
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
.workbench
.WorkbenchUiPlugin
;
36 import org
.argeo
.eclipse
.ui
.workbench
.internal
.jcr
.GenericNodeDoubleClickListener
;
37 import org
.argeo
.eclipse
.ui
.workbench
.internal
.jcr
.JcrBrowserUtils
;
38 import org
.argeo
.eclipse
.ui
.workbench
.internal
.jcr
.NodeContentProvider
;
39 import org
.argeo
.eclipse
.ui
.workbench
.internal
.jcr
.NodeLabelProvider
;
40 import org
.argeo
.eclipse
.ui
.workbench
.internal
.jcr
.PropertiesContentProvider
;
41 import org
.argeo
.eclipse
.ui
.workbench
.internal
.jcr
.model
.SingleJcrNodeElem
;
42 import org
.argeo
.jcr
.RepositoryRegister
;
43 import org
.argeo
.util
.security
.Keyring
;
44 import org
.eclipse
.jface
.action
.MenuManager
;
45 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
46 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
47 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
48 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
49 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
50 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
51 import org
.eclipse
.jface
.viewers
.TableViewer
;
52 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
53 import org
.eclipse
.jface
.viewers
.TreeViewer
;
54 import org
.eclipse
.swt
.SWT
;
55 import org
.eclipse
.swt
.custom
.SashForm
;
56 import org
.eclipse
.swt
.layout
.FillLayout
;
57 import org
.eclipse
.swt
.layout
.GridData
;
58 import org
.eclipse
.swt
.layout
.GridLayout
;
59 import org
.eclipse
.swt
.widgets
.Composite
;
60 import org
.eclipse
.swt
.widgets
.Display
;
61 import org
.eclipse
.swt
.widgets
.Menu
;
62 import org
.eclipse
.ui
.part
.ViewPart
;
65 * Basic View to display a sash form to browse a JCR compliant multiple
66 * repository environment
68 public class JcrBrowserView
extends ViewPart
{
69 public final static String ID
= WorkbenchUiPlugin
.ID
+ ".jcrBrowserView";
70 private boolean sortChildNodes
= true;
72 /* DEPENDENCY INJECTION */
73 private Keyring keyring
;
74 private RepositoryRegister repositoryRegister
;
75 private RepositoryFactory repositoryFactory
;
76 private Repository nodeRepository
;
78 // Current user session on the "Argeo node" default workspace
79 private Session userSession
;
82 private TreeViewer nodesViewer
;
83 private NodeContentProvider nodeContentProvider
;
84 private TableViewer propertiesViewer
;
85 private EventListener resultsObserver
;
88 public void createPartControl(Composite parent
) {
89 parent
.setLayout(new FillLayout());
90 SashForm sashForm
= new SashForm(parent
, SWT
.VERTICAL
);
91 sashForm
.setSashWidth(4);
92 sashForm
.setLayout(new FillLayout());
94 // Create the tree on top of the view
95 Composite top
= new Composite(sashForm
, SWT
.NONE
);
96 GridLayout gl
= new GridLayout(1, false);
100 this.userSession
= this.nodeRepository
.login();
101 } catch (RepositoryException e
) {
102 throw new ArgeoException("Cannot open user session", e
);
105 nodeContentProvider
= new NodeContentProvider(userSession
, keyring
,
106 repositoryRegister
, repositoryFactory
, sortChildNodes
);
109 nodesViewer
= createNodeViewer(top
, nodeContentProvider
);
111 // context menu : it is completely defined in the plugin.xml file.
112 MenuManager menuManager
= new MenuManager();
113 Menu menu
= menuManager
.createContextMenu(nodesViewer
.getTree());
115 nodesViewer
.getTree().setMenu(menu
);
116 getSite().registerContextMenu(menuManager
, nodesViewer
);
117 getSite().setSelectionProvider(nodesViewer
);
119 nodesViewer
.setInput(getViewSite());
121 // Create the property viewer on the bottom
122 Composite bottom
= new Composite(sashForm
, SWT
.NONE
);
123 bottom
.setLayout(new GridLayout(1, false));
124 propertiesViewer
= createPropertiesViewer(bottom
);
126 sashForm
.setWeights(getWeights());
127 nodesViewer
.setComparer(new NodeViewerComparer());
130 public void refresh(Object obj
) {
131 // Enable full refresh from a command when no element of the tree is
134 Object
[] elements
= nodeContentProvider
.getElements(null);
135 for (Object el
: elements
) {
136 if (el
instanceof TreeParent
)
137 JcrBrowserUtils
.forceRefreshIfNeeded((TreeParent
) el
);
138 getNodeViewer().refresh(el
);
141 getNodeViewer().refresh(obj
);
145 * To be overridden to adapt size of form and result frames.
147 protected int[] getWeights() {
148 return new int[] { 70, 30 };
151 protected TreeViewer
createNodeViewer(Composite parent
,
152 final ITreeContentProvider nodeContentProvider
) {
154 final TreeViewer tmpNodeViewer
= new TreeViewer(parent
, SWT
.MULTI
);
156 tmpNodeViewer
.getTree().setLayoutData(
157 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
159 tmpNodeViewer
.setContentProvider(nodeContentProvider
);
160 tmpNodeViewer
.setLabelProvider(new NodeLabelProvider());
162 .addSelectionChangedListener(new ISelectionChangedListener() {
163 public void selectionChanged(SelectionChangedEvent event
) {
164 if (!event
.getSelection().isEmpty()) {
165 IStructuredSelection sel
= (IStructuredSelection
) event
167 Object firstItem
= sel
.getFirstElement();
168 if (firstItem
instanceof SingleJcrNodeElem
)
170 .setInput(((SingleJcrNodeElem
) firstItem
)
173 propertiesViewer
.setInput(getViewSite());
178 resultsObserver
= new TreeObserver(tmpNodeViewer
.getTree().getDisplay());
181 ObservationManager observationManager
= userSession
182 .getWorkspace().getObservationManager();
183 observationManager
.addEventListener(resultsObserver
,
184 Event
.PROPERTY_ADDED
| Event
.PROPERTY_CHANGED
, "/",
185 true, null, null, false);
186 } catch (RepositoryException e
) {
187 throw new ArgeoException("Cannot register listeners", e
);
191 .addDoubleClickListener(new GenericNodeDoubleClickListener(
193 return tmpNodeViewer
;
196 protected TableViewer
createPropertiesViewer(Composite parent
) {
197 propertiesViewer
= new TableViewer(parent
);
198 propertiesViewer
.getTable().setLayoutData(
199 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
200 propertiesViewer
.getTable().setHeaderVisible(true);
201 propertiesViewer
.setContentProvider(new PropertiesContentProvider());
202 TableViewerColumn col
= new TableViewerColumn(propertiesViewer
,
204 col
.getColumn().setText("Name");
205 col
.getColumn().setWidth(200);
206 col
.setLabelProvider(new ColumnLabelProvider() {
207 private static final long serialVersionUID
= -6684361063107478595L;
209 public String
getText(Object element
) {
211 return ((Property
) element
).getName();
212 } catch (RepositoryException e
) {
213 throw new ArgeoException(
214 "Unexpected exception in label provider", e
);
218 col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
219 col
.getColumn().setText("Value");
220 col
.getColumn().setWidth(400);
221 col
.setLabelProvider(new ColumnLabelProvider() {
222 private static final long serialVersionUID
= -8201994187693336657L;
224 public String
getText(Object element
) {
226 Property property
= (Property
) element
;
227 if (property
.getType() == PropertyType
.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
++) {
235 buf
.append(values
[i
].getString());
238 return buf
.toString();
240 return property
.getValue().getString();
241 } catch (RepositoryException e
) {
242 throw new ArgeoException(
243 "Unexpected exception in label provider", e
);
247 col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
248 col
.getColumn().setText("Type");
249 col
.getColumn().setWidth(200);
250 col
.setLabelProvider(new ColumnLabelProvider() {
251 private static final long serialVersionUID
= -6009599998150286070L;
253 public String
getText(Object element
) {
255 return PropertyType
.nameFromValue(((Property
) element
)
257 } catch (RepositoryException e
) {
258 throw new ArgeoException(
259 "Unexpected exception in label provider", e
);
263 propertiesViewer
.setInput(getViewSite());
264 return propertiesViewer
;
268 public void dispose() {
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())
286 .setSortChildren(sortChildNodes
);
287 nodesViewer
.setInput(getViewSite());
290 /** Notifies the current view that a node has been added */
291 public void nodeAdded(TreeParent parentNode
) {
292 // insure that Ui objects have been correctly created:
293 JcrBrowserUtils
.forceRefreshIfNeeded(parentNode
);
294 getNodeViewer().refresh(parentNode
);
295 getNodeViewer().expandToLevel(parentNode
, 1);
298 /** Notifies the current view that a node has been removed */
299 public void nodeRemoved(TreeParent parentNode
) {
300 IStructuredSelection newSel
= new StructuredSelection(parentNode
);
301 getNodeViewer().setSelection(newSel
, true);
303 IStructuredSelection tmpSel
= (IStructuredSelection
) getNodeViewer()
305 getNodeViewer().refresh(tmpSel
.getFirstElement());
308 class TreeObserver
extends AsyncUiEventListener
{
310 public TreeObserver(Display display
) {
315 protected Boolean
willProcessInUiThread(List
<Event
> events
)
316 throws RepositoryException
{
317 for (Event event
: events
) {
318 if (getLog().isTraceEnabled())
319 getLog().debug("Received event " + event
);
320 String path
= event
.getPath();
321 int index
= path
.lastIndexOf('/');
322 String propertyName
= path
.substring(index
+ 1);
323 if (getLog().isTraceEnabled())
324 getLog().debug("Concerned property " + propertyName
);
329 protected void onEventInUiThread(List
<Event
> events
)
330 throws RepositoryException
{
331 if (getLog().isTraceEnabled())
332 getLog().trace("Refresh result list");
333 nodesViewer
.refresh();
338 public boolean getSortChildNodes() {
339 return sortChildNodes
;
343 public void setFocus() {
344 getNodeViewer().getTree().setFocus();
347 /* DEPENDENCY INJECTION */
348 public void setRepositoryRegister(RepositoryRegister repositoryRegister
) {
349 this.repositoryRegister
= repositoryRegister
;
352 public void setKeyring(Keyring keyring
) {
353 this.keyring
= keyring
;
356 public void setRepositoryFactory(RepositoryFactory repositoryFactory
) {
357 this.repositoryFactory
= repositoryFactory
;
360 public void setNodeRepository(Repository nodeRepository
) {
361 this.nodeRepository
= nodeRepository
;