1 package org
.argeo
.cms
.e4
.jcr
;
5 import javax
.annotation
.PostConstruct
;
6 import javax
.annotation
.PreDestroy
;
7 import javax
.inject
.Inject
;
8 import javax
.jcr
.Property
;
9 import javax
.jcr
.PropertyType
;
10 import javax
.jcr
.Repository
;
11 import javax
.jcr
.RepositoryException
;
12 import javax
.jcr
.RepositoryFactory
;
13 import javax
.jcr
.Session
;
14 import javax
.jcr
.Value
;
15 import javax
.jcr
.observation
.Event
;
16 import javax
.jcr
.observation
.EventListener
;
17 import javax
.jcr
.observation
.ObservationManager
;
19 import org
.argeo
.api
.cms
.CmsConstants
;
20 import org
.argeo
.cms
.security
.CryptoKeyring
;
21 import org
.argeo
.cms
.security
.Keyring
;
22 import org
.argeo
.cms
.swt
.CmsException
;
23 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
24 import org
.argeo
.cms
.ui
.jcr
.JcrBrowserUtils
;
25 import org
.argeo
.cms
.ui
.jcr
.NodeContentProvider
;
26 import org
.argeo
.cms
.ui
.jcr
.NodeLabelProvider
;
27 import org
.argeo
.cms
.ui
.jcr
.OsgiRepositoryRegister
;
28 import org
.argeo
.cms
.ui
.jcr
.PropertiesContentProvider
;
29 import org
.argeo
.cms
.ui
.jcr
.model
.SingleJcrNodeElem
;
30 import org
.argeo
.cms
.ux
.widgets
.TreeParent
;
31 import org
.argeo
.eclipse
.ui
.EclipseUiException
;
32 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
33 import org
.argeo
.eclipse
.ui
.jcr
.util
.NodeViewerComparer
;
34 import org
.argeo
.jcr
.JcrUtils
;
35 import org
.eclipse
.e4
.core
.contexts
.IEclipseContext
;
36 import org
.eclipse
.e4
.core
.di
.annotations
.Optional
;
37 import org
.eclipse
.e4
.ui
.services
.EMenuService
;
38 import org
.eclipse
.e4
.ui
.workbench
.modeling
.EPartService
;
39 import org
.eclipse
.e4
.ui
.workbench
.modeling
.ESelectionService
;
40 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
41 import org
.eclipse
.jface
.viewers
.IBaseLabelProvider
;
42 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
43 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
44 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
45 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
46 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
47 import org
.eclipse
.jface
.viewers
.TableViewer
;
48 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
49 import org
.eclipse
.jface
.viewers
.TreeViewer
;
50 import org
.eclipse
.swt
.SWT
;
51 import org
.eclipse
.swt
.custom
.SashForm
;
52 import org
.eclipse
.swt
.layout
.FillLayout
;
53 import org
.eclipse
.swt
.layout
.GridData
;
54 import org
.eclipse
.swt
.widgets
.Composite
;
55 import org
.eclipse
.swt
.widgets
.Display
;
58 * Basic View to display a sash form to browse a JCR compliant multiple
59 * repository environment
61 public class JcrBrowserView
{
62 final static String ID
= "org.argeo.cms.e4.jcrbrowser";
63 final static String NODE_VIEWER_POPUP_MENU_ID
= "org.argeo.cms.e4.popupmenu.nodeViewer";
65 private boolean sortChildNodes
= true;
67 /* DEPENDENCY INJECTION */
70 private Keyring keyring
;
72 private RepositoryFactory repositoryFactory
;
74 private Repository nodeRepository
;
76 // Current user session on the home repository default workspace
77 private Session userSession
;
79 private OsgiRepositoryRegister repositoryRegister
= new OsgiRepositoryRegister();
82 private TreeViewer nodesViewer
;
83 private NodeContentProvider nodeContentProvider
;
84 private TableViewer propertiesViewer
;
85 private EventListener resultsObserver
;
88 public void createPartControl(Composite parent
, IEclipseContext context
, EPartService partService
,
89 ESelectionService selectionService
, EMenuService menuService
) {
90 repositoryRegister
.init();
92 parent
.setLayout(new FillLayout());
93 SashForm sashForm
= new SashForm(parent
, SWT
.VERTICAL
);
94 // sashForm.setSashWidth(4);
95 // sashForm.setLayout(new FillLayout());
97 // Create the tree on top of the view
98 Composite top
= new Composite(sashForm
, SWT
.NONE
);
99 // GridLayout gl = new GridLayout(1, false);
100 top
.setLayout(CmsSwtUtils
.noSpaceGridLayout());
103 this.userSession
= this.nodeRepository
.login(CmsConstants
.HOME_WORKSPACE
);
104 } catch (RepositoryException e
) {
105 throw new CmsException("Cannot open user session", e
);
108 nodeContentProvider
= new NodeContentProvider(userSession
, keyring
, repositoryRegister
, repositoryFactory
,
112 nodesViewer
= createNodeViewer(top
, nodeContentProvider
);
114 // context menu : it is completely defined in the plugin.xml file.
115 // MenuManager menuManager = new MenuManager();
116 // Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
118 // nodesViewer.getTree().setMenu(menu);
120 nodesViewer
.setInput("");
122 // Create the property viewer on the bottom
123 Composite bottom
= new Composite(sashForm
, SWT
.NONE
);
124 bottom
.setLayout(CmsSwtUtils
.noSpaceGridLayout());
125 propertiesViewer
= createPropertiesViewer(bottom
);
127 sashForm
.setWeights(getWeights());
128 nodesViewer
.setComparer(new NodeViewerComparer());
129 nodesViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
130 public void selectionChanged(SelectionChangedEvent event
) {
131 IStructuredSelection selection
= (IStructuredSelection
) event
.getSelection();
132 selectionService
.setSelection(selection
.toList());
135 nodesViewer
.addDoubleClickListener(new JcrE4DClickListener(nodesViewer
, partService
));
136 menuService
.registerContextMenu(nodesViewer
.getControl(), NODE_VIEWER_POPUP_MENU_ID
);
137 // getSite().registerContextMenu(menuManager, nodesViewer);
138 // getSite().setSelectionProvider(nodesViewer);
142 public void dispose() {
143 JcrUtils
.logoutQuietly(userSession
);
144 repositoryRegister
.destroy();
147 public void refresh(Object obj
) {
148 // Enable full refresh from a command when no element of the tree is
151 Object
[] elements
= nodeContentProvider
.getElements(null);
152 for (Object el
: elements
) {
153 if (el
instanceof TreeParent
)
154 JcrBrowserUtils
.forceRefreshIfNeeded((TreeParent
) el
);
155 getNodeViewer().refresh(el
);
158 getNodeViewer().refresh(obj
);
162 * To be overridden to adapt size of form and result frames.
164 protected int[] getWeights() {
165 return new int[] { 70, 30 };
168 protected TreeViewer
createNodeViewer(Composite parent
, final ITreeContentProvider nodeContentProvider
) {
170 final TreeViewer tmpNodeViewer
= new TreeViewer(parent
, SWT
.MULTI
);
172 tmpNodeViewer
.getTree().setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
174 tmpNodeViewer
.setContentProvider(nodeContentProvider
);
175 tmpNodeViewer
.setLabelProvider((IBaseLabelProvider
) new NodeLabelProvider());
176 tmpNodeViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
177 public void selectionChanged(SelectionChangedEvent event
) {
178 if (!event
.getSelection().isEmpty()) {
179 IStructuredSelection sel
= (IStructuredSelection
) event
.getSelection();
180 Object firstItem
= sel
.getFirstElement();
181 if (firstItem
instanceof SingleJcrNodeElem
)
182 propertiesViewer
.setInput(((SingleJcrNodeElem
) firstItem
).getNode());
184 propertiesViewer
.setInput("");
189 resultsObserver
= new TreeObserver(tmpNodeViewer
.getTree().getDisplay());
192 ObservationManager observationManager
= userSession
.getWorkspace().getObservationManager();
193 observationManager
.addEventListener(resultsObserver
, Event
.PROPERTY_ADDED
| Event
.PROPERTY_CHANGED
, "/",
194 true, null, null, false);
195 } catch (RepositoryException e
) {
196 throw new EclipseUiException("Cannot register listeners", e
);
199 // tmpNodeViewer.addDoubleClickListener(new JcrDClickListener(tmpNodeViewer));
200 return tmpNodeViewer
;
203 protected TableViewer
createPropertiesViewer(Composite parent
) {
204 propertiesViewer
= new TableViewer(parent
, SWT
.NONE
);
205 propertiesViewer
.getTable().setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
206 propertiesViewer
.getTable().setHeaderVisible(true);
207 propertiesViewer
.setContentProvider(new PropertiesContentProvider());
208 TableViewerColumn col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
209 col
.getColumn().setText("Name");
210 col
.getColumn().setWidth(200);
211 col
.setLabelProvider(new ColumnLabelProvider() {
212 private static final long serialVersionUID
= -6684361063107478595L;
214 public String
getText(Object element
) {
216 return ((Property
) element
).getName();
217 } catch (RepositoryException e
) {
218 throw new EclipseUiException("Unexpected exception in label provider", e
);
222 col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
223 col
.getColumn().setText("Value");
224 col
.getColumn().setWidth(400);
225 col
.setLabelProvider(new ColumnLabelProvider() {
226 private static final long serialVersionUID
= -8201994187693336657L;
228 public String
getText(Object element
) {
230 Property property
= (Property
) element
;
231 if (property
.getType() == PropertyType
.BINARY
)
233 else if (property
.isMultiple()) {
234 StringBuffer buf
= new StringBuffer("[");
235 Value
[] values
= property
.getValues();
236 for (int i
= 0; i
< values
.length
; i
++) {
239 buf
.append(values
[i
].getString());
242 return buf
.toString();
244 return property
.getValue().getString();
245 } catch (RepositoryException e
) {
246 throw new EclipseUiException("Unexpected exception in label provider", e
);
250 col
= new TableViewerColumn(propertiesViewer
, SWT
.NONE
);
251 col
.getColumn().setText("Type");
252 col
.getColumn().setWidth(200);
253 col
.setLabelProvider(new ColumnLabelProvider() {
254 private static final long serialVersionUID
= -6009599998150286070L;
256 public String
getText(Object element
) {
257 return JcrBrowserUtils
.getPropertyTypeAsString((Property
) element
);
260 propertiesViewer
.setInput("");
261 return propertiesViewer
;
264 protected TreeViewer
getNodeViewer() {
269 * Resets the tree content provider
271 * @param sortChildNodes if true the content provider will use a comparer to
272 * sort nodes that might slow down the display
274 public void setSortChildNodes(boolean sortChildNodes
) {
275 this.sortChildNodes
= sortChildNodes
;
276 ((NodeContentProvider
) nodesViewer
.getContentProvider()).setSortChildren(sortChildNodes
);
277 nodesViewer
.setInput("");
280 /** Notifies the current view that a node has been added */
281 public void nodeAdded(TreeParent parentNode
) {
282 // insure that Ui objects have been correctly created:
283 JcrBrowserUtils
.forceRefreshIfNeeded(parentNode
);
284 getNodeViewer().refresh(parentNode
);
285 getNodeViewer().expandToLevel(parentNode
, 1);
288 /** Notifies the current view that a node has been removed */
289 public void nodeRemoved(TreeParent parentNode
) {
290 IStructuredSelection newSel
= new StructuredSelection(parentNode
);
291 getNodeViewer().setSelection(newSel
, true);
293 IStructuredSelection tmpSel
= (IStructuredSelection
) getNodeViewer().getSelection();
294 getNodeViewer().refresh(tmpSel
.getFirstElement());
297 class TreeObserver
extends AsyncUiEventListener
{
299 public TreeObserver(Display display
) {
304 protected Boolean
willProcessInUiThread(List
<Event
> events
) throws RepositoryException
{
305 for (Event event
: events
) {
306 if (getLog().isTraceEnabled())
307 getLog().debug("Received event " + event
);
308 String path
= event
.getPath();
309 int index
= path
.lastIndexOf('/');
310 String propertyName
= path
.substring(index
+ 1);
311 if (getLog().isTraceEnabled())
312 getLog().debug("Concerned property " + propertyName
);
317 protected void onEventInUiThread(List
<Event
> events
) throws RepositoryException
{
318 if (getLog().isTraceEnabled())
319 getLog().trace("Refresh result list");
320 nodesViewer
.refresh();
325 public boolean getSortChildNodes() {
326 return sortChildNodes
;
329 public void setFocus() {
330 getNodeViewer().getTree().setFocus();
333 /* DEPENDENCY INJECTION */
334 // public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
335 // this.repositoryRegister = repositoryRegister;
338 public void setKeyring(CryptoKeyring keyring
) {
339 this.keyring
= keyring
;
342 public void setRepositoryFactory(RepositoryFactory repositoryFactory
) {
343 this.repositoryFactory
= repositoryFactory
;
346 public void setNodeRepository(Repository nodeRepository
) {
347 this.nodeRepository
= nodeRepository
;