1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.argeo.documents.e4.parts;
17
18 import java.net.URI;
19 import java.net.URISyntaxException;
20 import java.nio.file.Path;
21 import java.nio.file.spi.FileSystemProvider;
22 import java.util.List;
23
24 import javax.annotation.PostConstruct;
25 import javax.annotation.PreDestroy;
26 import javax.inject.Inject;
27 import javax.inject.Named;
28 import javax.jcr.Node;
29 import javax.jcr.NodeIterator;
30 import javax.jcr.Repository;
31 import javax.jcr.RepositoryException;
32 import javax.jcr.Session;
33 import javax.jcr.query.Query;
34 import javax.jcr.query.QueryManager;
35 import javax.jcr.query.QueryResult;
36
37 import org.argeo.cms.util.CmsUtils;
38 import org.argeo.connect.ui.ConnectUiConstants;
39 import org.argeo.connect.ui.Refreshable;
40 import org.argeo.connect.ui.SystemWorkbenchService;
41 import org.argeo.connect.ui.widgets.DelayedText;
42 import org.argeo.connect.util.ConnectJcrUtils;
43 import org.argeo.connect.util.XPathUtils;
44 import org.argeo.documents.DocumentsException;
45 import org.argeo.documents.DocumentsNames;
46 import org.argeo.documents.DocumentsService;
47 import org.argeo.documents.DocumentsTypes;
48 import org.argeo.documents.composites.BookmarksTableViewer;
49 import org.argeo.eclipse.ui.EclipseUiUtils;
50 import org.argeo.eclipse.ui.fs.FsTableViewer;
51 import org.argeo.jcr.JcrUtils;
52 import org.argeo.node.NodeNames;
53 import org.argeo.node.NodeTypes;
54 import org.eclipse.jface.dialogs.MessageDialog;
55 import org.eclipse.jface.layout.TableColumnLayout;
56 import org.eclipse.jface.viewers.CellLabelProvider;
57 import org.eclipse.jface.viewers.ColumnLabelProvider;
58 import org.eclipse.jface.viewers.ColumnWeightData;
59 import org.eclipse.jface.viewers.DoubleClickEvent;
60 import org.eclipse.jface.viewers.IDoubleClickListener;
61 import org.eclipse.jface.viewers.ILabelProvider;
62 import org.eclipse.jface.viewers.IStructuredContentProvider;
63 import org.eclipse.jface.viewers.IStructuredSelection;
64 import org.eclipse.jface.viewers.StructuredSelection;
65 import org.eclipse.jface.viewers.TableViewer;
66 import org.eclipse.jface.viewers.Viewer;
67 import org.eclipse.swt.SWT;
68 import org.eclipse.swt.events.KeyEvent;
69 import org.eclipse.swt.events.KeyListener;
70 import org.eclipse.swt.events.ModifyEvent;
71 import org.eclipse.swt.events.ModifyListener;
72 import org.eclipse.swt.graphics.Image;
73 import org.eclipse.swt.layout.GridData;
74 import org.eclipse.swt.layout.GridLayout;
75 import org.eclipse.swt.widgets.Composite;
76 import org.eclipse.swt.widgets.Label;
77 import org.eclipse.swt.widgets.Table;
78 import org.eclipse.swt.widgets.TableColumn;
79 import org.eclipse.swt.widgets.Text;
80
81
82 public class MyFilesView implements IDoubleClickListener, Refreshable {
83
84
85 @Inject
86 @Named("(cn=home)")
87 private Repository repository;
88 @Inject
89 private SystemWorkbenchService systemWorkbenchService;
90 @Inject
91 private FileSystemProvider nodeFileSystemProvider;
92 @Inject
93 private DocumentsService documentsService;
94
95 private Session session;
96 private Text filterTxt;
97 private TableViewer searchResultsViewer;
98 private Composite searchCmp;
99 private Composite bookmarkCmp;
100
101 @PostConstruct
102 public void createPartControl(Composite parent) {
103 session = ConnectJcrUtils.login(repository);
104
105 parent.setLayout(new GridLayout());
106
107
108
109
110
111
112
113
114 bookmarkCmp = new Composite(parent, SWT.NO_FOCUS);
115 bookmarkCmp.setLayoutData(EclipseUiUtils.fillAll());
116 populateBookmarks(bookmarkCmp);
117 }
118
119 @Override
120 public void forceRefresh(Object object) {
121 populateBookmarks(bookmarkCmp);
122 bookmarkCmp.getParent().layout(true, true);
123 }
124
125 public void addFilterPanel(Composite parent) {
126
127
128 int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL;
129 DelayedText delayedText = new DelayedText(parent, style, ConnectUiConstants.SEARCH_TEXT_DELAY);
130 filterTxt = delayedText.getText();
131 filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
132
133
134 delayedText.addDelayedModifyListener(null, new ModifyListener() {
135 private static final long serialVersionUID = 5003010530960334977L;
136
137 public void modifyText(ModifyEvent event) {
138 delayedText.getText().getDisplay().asyncExec(new Runnable() {
139 @Override
140 public void run() {
141 int resultNb = refreshFilteredList();
142 if (resultNb > 0)
143 ((GridData) searchCmp.getLayoutData()).heightHint = 120;
144 else
145 ((GridData) searchCmp.getLayoutData()).heightHint = 0;
146 parent.layout(true, true);
147 }
148 });
149
150 }
151 });
152
153
154 filterTxt.addKeyListener(new KeyListener() {
155 private static final long serialVersionUID = -4523394262771183968L;
156
157 @Override
158 public void keyReleased(KeyEvent e) {
159 }
160
161 @Override
162 public void keyPressed(KeyEvent e) {
163
164
165 if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.TAB) {
166 Object first = searchResultsViewer.getElementAt(0);
167 if (first != null) {
168 searchResultsViewer.getTable().setFocus();
169 searchResultsViewer.setSelection(new StructuredSelection(first), true);
170 }
171 e.doit = false;
172 }
173 }
174 });
175 }
176
177 protected TableViewer createListPart(Composite parent, ILabelProvider labelProvider) {
178 parent.setLayout(new GridLayout());
179
180 Composite tableComposite = new Composite(parent, SWT.NONE);
181 tableComposite.setLayoutData(EclipseUiUtils.fillAll());
182
183 TableViewer v = new TableViewer(tableComposite);
184 v.setLabelProvider(labelProvider);
185
186 TableColumn singleColumn = new TableColumn(v.getTable(), SWT.V_SCROLL);
187 TableColumnLayout tableColumnLayout = new TableColumnLayout();
188 tableColumnLayout.setColumnData(singleColumn, new ColumnWeightData(100));
189 tableComposite.setLayout(tableColumnLayout);
190
191
192 Table table = v.getTable();
193 table.setLinesVisible(false);
194 table.setHeaderVisible(false);
195 CmsUtils.markup(table);
196 CmsUtils.setItemHeight(table, 26);
197
198 v.setContentProvider(new BasicNodeListContentProvider());
199 v.addDoubleClickListener(this);
200 return v;
201 }
202
203 @PreDestroy
204 public void dispose() {
205 JcrUtils.logoutQuietly(session);
206 }
207
208 protected int refreshFilteredList() {
209 try {
210 String filter = filterTxt.getText();
211 if (EclipseUiUtils.isEmpty(filter)) {
212 searchResultsViewer.setInput(null);
213 return 0;
214 }
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 String cf = XPathUtils.encodeXPathStringValue(filter);
231 String qStr = "SELECT * FROM [nt:hierarchyNode] WHERE UPPER(LOCALNAME()) LIKE '%" + cf.toUpperCase() + "%'";
232 QueryManager queryManager = session.getWorkspace().getQueryManager();
233 Query xpathQuery = queryManager.createQuery(qStr, Query.JCR_SQL2);
234
235
236 QueryResult result = xpathQuery.execute();
237 NodeIterator nit = result.getNodes();
238 searchResultsViewer.setInput(JcrUtils.nodeIteratorToList(nit));
239
240 return (int) nit.getSize();
241 } catch (RepositoryException e) {
242 throw new DocumentsException("Unable to list files", e);
243 }
244 }
245
246 private void populateBookmarks(Composite parent) {
247 CmsUtils.clear(parent);
248 GridLayout layout = EclipseUiUtils.noSpaceGridLayout();
249 layout.verticalSpacing = 5;
250 parent.setLayout(layout);
251 int bookmarkColWith = 200;
252
253 CellLabelProvider lp = new MyLabelProvider();
254
255 FsTableViewer homeViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL);
256 Table table = homeViewer.configureDefaultSingleColumnTable(bookmarkColWith, lp);
257 GridData gd = EclipseUiUtils.fillWidth();
258 gd.horizontalIndent = 10;
259 table.setLayoutData(gd);
260 homeViewer.addDoubleClickListener(this);
261 homeViewer.setPathsInput(documentsService.getMyDocumentsPath(nodeFileSystemProvider, session));
262
263 Path[] wkGpHomes = documentsService.getMyGroupsFilesPath(nodeFileSystemProvider, session);
264 if (wkGpHomes != null && wkGpHomes.length > 0) {
265 appendTitle(parent, "Shared");
266 FsTableViewer groupsViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL);
267 table = groupsViewer.configureDefaultSingleColumnTable(bookmarkColWith, lp);
268 gd = EclipseUiUtils.fillWidth();
269 gd.horizontalIndent = 10;
270 table.setLayoutData(gd);
271 groupsViewer.addDoubleClickListener(this);
272 groupsViewer.setPathsInput(wkGpHomes);
273 }
274
275 appendTitle(parent, "Bookmarks");
276 BookmarksTableViewer bookmarksViewer = new BookmarksTableViewer(parent, SWT.MULTI | SWT.NO_SCROLL,
277 documentsService.getMyBookmarksParent(session), documentsService, systemWorkbenchService);
278 table = bookmarksViewer.configureDefaultSingleColumnTable(bookmarkColWith);
279 gd = EclipseUiUtils.fillWidth();
280 gd.horizontalIndent = 10;
281 table.setLayoutData(gd);
282 bookmarksViewer.addDoubleClickListener(this);
283 }
284
285 private class MyLabelProvider extends ColumnLabelProvider {
286 private static final long serialVersionUID = -3406927207142514035L;
287
288 public MyLabelProvider() {
289 super();
290 }
291
292 @Override
293 public String getText(Object element) {
294 Path curr = ((Path) element);
295 try {
296 String path = curr.toString();
297 Node currNode = session.getNode(path);
298
299 if (currNode.isNodeType(NodeTypes.NODE_USER_HOME))
300 return currNode.getName();
301 else if (currNode.isNodeType(NodeTypes.NODE_GROUP_HOME))
302 return currNode.getProperty(NodeNames.LDAP_CN).getString();
303
304 else
305 return super.getText(element);
306 } catch (RepositoryException e) {
307 throw new DocumentsException("Cannot retrieve label for " + curr, e);
308 }
309 }
310
311 @Override
312 public Image getImage(Object element) {
313 if (element instanceof Path) {
314 Path curr = ((Path) element);
315 String path = curr.toString();
316 Node currNode = ConnectJcrUtils.getNode(session, path);
317 return systemWorkbenchService.getIconForType(currNode);
318 }
319 return null;
320 }
321 }
322
323 private Label appendTitle(Composite parent, String value) {
324 Label titleLbl = new Label(parent, SWT.NONE);
325 titleLbl.setText(value);
326 titleLbl.setFont(EclipseUiUtils.getBoldFont(parent));
327 GridData gd = EclipseUiUtils.fillWidth();
328 gd.horizontalIndent = 5;
329 gd.verticalIndent = 5;
330 titleLbl.setLayoutData(gd);
331 return titleLbl;
332 }
333
334 @Override
335 public void doubleClick(DoubleClickEvent event) {
336 IStructuredSelection selection = (IStructuredSelection) event.getSelection();
337 if (selection.isEmpty())
338 return;
339 else {
340 Object element = selection.getFirstElement();
341 Node currNode;
342
343 if (element instanceof Node) {
344 Node tmpNode = (Node) element;
345 if (ConnectJcrUtils.isNodeType(tmpNode, DocumentsTypes.DOCUMENTS_BOOKMARK)) {
346 String uriStr = ConnectJcrUtils.get(tmpNode, DocumentsNames.DOCUMENTS_URI);
347 try {
348 Path currPath = documentsService.getPath(nodeFileSystemProvider, new URI(uriStr));
349 String jcrPath = currPath.toString();
350 if (!session.itemExists(jcrPath)) {
351 String msg = "Bookmarked folder at URI " + uriStr
352 + " cannot be found. If it is a local folder "
353 + "it has been removed or renamed.\nDo you want to delete corresponding bookmark?";
354 boolean remove = MessageDialog.openConfirm(event.getViewer().getControl().getShell(),
355 "Missing target folder", msg);
356 if (remove) {
357 tmpNode.remove();
358 session.save();
359 forceRefresh(null);
360 }
361 return;
362 } else
363 currNode = session.getNode(jcrPath);
364 } catch (URISyntaxException | RepositoryException e) {
365 throw new DocumentsException("Cannot get target node for bookmark " + tmpNode, e);
366 }
367 } else
368 currNode = tmpNode;
369 } else if (element instanceof Path) {
370 Path currPath = (Path) element;
371 String jcrPath = currPath.toString();
372
373 currNode = ConnectJcrUtils.getNode(session, jcrPath);
374 } else
375 throw new IllegalArgumentException("Cannot manage " + element + ", only Node and Path are supported.");
376
377
378
379
380 systemWorkbenchService.openEntityEditor(currNode);
381 }
382 }
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403 private class BasicNodeListContentProvider implements IStructuredContentProvider {
404 private static final long serialVersionUID = 1L;
405 private List<Node> nodes;
406
407 public void dispose() {
408 }
409
410
411 @SuppressWarnings("unchecked")
412 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
413 nodes = (List<Node>) newInput;
414 }
415
416 public Object[] getElements(Object arg0) {
417 return nodes.toArray();
418 }
419 }
420 }