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