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