]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.client.ui.dist/src/org/argeo/slc/client/ui/dist/editors/WkspCategoryBaseListPage.java
Adapt to changes in Argeo Commons.
[gpl/argeo-slc.git] / org.argeo.slc.client.ui.dist / src / org / argeo / slc / client / ui / dist / editors / WkspCategoryBaseListPage.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 package org.argeo.slc.client.ui.dist.editors;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import javax.jcr.Node;
24 import javax.jcr.NodeIterator;
25 import javax.jcr.PropertyType;
26 import javax.jcr.RepositoryException;
27 import javax.jcr.Session;
28 import javax.jcr.observation.Event;
29 import javax.jcr.query.QueryManager;
30 import javax.jcr.query.QueryResult;
31 import javax.jcr.query.qom.Constraint;
32 import javax.jcr.query.qom.DynamicOperand;
33 import javax.jcr.query.qom.QueryObjectModel;
34 import javax.jcr.query.qom.QueryObjectModelFactory;
35 import javax.jcr.query.qom.Selector;
36 import javax.jcr.query.qom.StaticOperand;
37
38 import org.argeo.cms.ui.workbench.util.CommandUtils;
39 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
40 import org.argeo.jcr.JcrUtils;
41 import org.argeo.slc.SlcException;
42 import org.argeo.slc.SlcNames;
43 import org.argeo.slc.SlcTypes;
44 import org.argeo.slc.client.ui.dist.DistConstants;
45 import org.argeo.slc.client.ui.dist.DistImages;
46 import org.argeo.slc.client.ui.dist.DistPlugin;
47 import org.argeo.slc.client.ui.dist.commands.OpenGenerateBinariesWizard;
48 import org.argeo.slc.client.ui.dist.commands.OpenModuleEditor;
49 import org.argeo.slc.client.ui.dist.utils.DistNodeViewerComparator;
50 import org.argeo.slc.repo.RepoConstants;
51 import org.eclipse.jface.action.IMenuListener;
52 import org.eclipse.jface.action.IMenuManager;
53 import org.eclipse.jface.action.MenuManager;
54 import org.eclipse.jface.dialogs.IMessageProvider;
55 import org.eclipse.jface.viewers.ColumnLabelProvider;
56 import org.eclipse.jface.viewers.DoubleClickEvent;
57 import org.eclipse.jface.viewers.IDoubleClickListener;
58 import org.eclipse.jface.viewers.IStructuredContentProvider;
59 import org.eclipse.jface.viewers.IStructuredSelection;
60 import org.eclipse.jface.viewers.TableViewer;
61 import org.eclipse.jface.viewers.TableViewerColumn;
62 import org.eclipse.jface.viewers.Viewer;
63 import org.eclipse.swt.SWT;
64 import org.eclipse.swt.events.ModifyEvent;
65 import org.eclipse.swt.events.ModifyListener;
66 import org.eclipse.swt.events.SelectionAdapter;
67 import org.eclipse.swt.events.SelectionEvent;
68 import org.eclipse.swt.layout.FillLayout;
69 import org.eclipse.swt.layout.GridData;
70 import org.eclipse.swt.layout.GridLayout;
71 import org.eclipse.swt.widgets.Button;
72 import org.eclipse.swt.widgets.Composite;
73 import org.eclipse.swt.widgets.Display;
74 import org.eclipse.swt.widgets.Menu;
75 import org.eclipse.swt.widgets.Table;
76 import org.eclipse.swt.widgets.Text;
77 import org.eclipse.ui.IWorkbenchWindow;
78 import org.eclipse.ui.forms.IManagedForm;
79 import org.eclipse.ui.forms.editor.FormEditor;
80 import org.eclipse.ui.forms.editor.FormPage;
81 import org.eclipse.ui.forms.widgets.FormToolkit;
82 import org.eclipse.ui.forms.widgets.ScrolledForm;
83
84 /**
85 * Show all category base (currently only Aether group base) contained in a
86 * given workspace as filter-able table. Enable to definition of which of them
87 * should be managed as modular distribution
88 */
89 public class WkspCategoryBaseListPage extends FormPage implements SlcNames {
90
91 final static String PAGE_ID = "WkspCategoryBaseListPage";
92
93 // Business Objects
94 private Session session;
95
96 // This page widgets
97 private DistNodeViewerComparator comparator;
98 private TableViewer viewer;
99 private FormToolkit tk;
100 private Text filterTxt;
101 private final static String FILTER_HELP_MSG = "Enter filter criterion separated by a space";
102
103 // Observes changes
104 // private final static String[] observedTypes = { SlcTypes.SLC_GROUP_BASE
105 // };
106 // private CategoryObserver categoriesObserver;
107
108 public WkspCategoryBaseListPage(FormEditor formEditor, String title,
109 Session session) {
110 super(formEditor, PAGE_ID, title);
111 this.session = session;
112 }
113
114 @Override
115 protected void createFormContent(IManagedForm managedForm) {
116 ScrolledForm form = managedForm.getForm();
117 tk = managedForm.getToolkit();
118
119 form.setText("Define Relevant Categories");
120 form.setMessage("Choose in the below list "
121 + "the categories that can be used as base for "
122 + "modular distributions maintained via the current workspace",
123 IMessageProvider.NONE);
124
125 // Main Layout
126 GridLayout layout = new GridLayout(1, false);
127 Composite body = form.getBody();
128 body.setLayout(layout);
129
130 // filter section
131 Composite header = tk.createComposite(body);
132 header.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
133 createFilterPart(header);
134
135 // the table
136 Composite tableCmp = tk.createComposite(body);
137 tableCmp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
138 createTableViewer(tableCmp);
139
140 // categoriesObserver = new CategoryObserver(viewer.getTable()
141 // .getDisplay());
142 // try {
143 // ObservationManager observationManager = session.getWorkspace()
144 // .getObservationManager();
145 // // FIXME Will not be notified if empty result is deleted
146 // observationManager.addEventListener(categoriesObserver,
147 // Event.PROPERTY_CHANGED, "/", true, null, observedTypes,
148 // false);
149 // } catch (RepositoryException e) {
150 // throw new SlcException("Cannot register listeners", e);
151 // }
152
153 refresh();
154 }
155
156 private void refresh() {
157 final List<Node> result = JcrUtils.nodeIteratorToList(listGroupBase());
158 viewer.setInput(result);
159 }
160
161 /** Build repository request */
162 private NodeIterator listGroupBase() {
163 try {
164 QueryManager queryManager = session.getWorkspace()
165 .getQueryManager();
166 QueryObjectModelFactory factory = queryManager.getQOMFactory();
167
168 Selector source = factory.selector(SlcTypes.SLC_GROUP_BASE,
169 SlcTypes.SLC_MODULE_COORDINATES);
170
171 // Create a dynamic operand for each property on which we want to
172 // filter
173 DynamicOperand catDO = factory.propertyValue(
174 source.getSelectorName(), SlcNames.SLC_CATEGORY);
175 DynamicOperand nameDO = factory.propertyValue(
176 source.getSelectorName(), SlcNames.SLC_NAME);
177
178 String filter = filterTxt.getText();
179
180 Constraint defaultC = null;
181 // Build constraints based the textArea content
182 if (filter != null && !"".equals(filter.trim())) {
183 // Parse the String
184 String[] strs = filter.trim().split(" ");
185 for (String token : strs) {
186 token = token.replace('*', '%');
187 StaticOperand so = factory.literal(session
188 .getValueFactory().createValue("%" + token + "%"));
189
190 Constraint currC = factory.comparison(catDO,
191 QueryObjectModelFactory.JCR_OPERATOR_LIKE, so);
192 currC = factory.or(currC, factory.comparison(nameDO,
193 QueryObjectModelFactory.JCR_OPERATOR_LIKE, so));
194
195 if (defaultC == null)
196 defaultC = currC;
197 else
198 defaultC = factory.and(defaultC, currC);
199 }
200 }
201
202 QueryObjectModel query = factory.createQuery(source, defaultC,
203 null, null);
204 QueryResult result = query.execute();
205 return result.getNodes();
206 } catch (RepositoryException re) {
207 throw new SlcException(
208 "Unable to refresh group list for workspace "
209 + getEditorInput().getName(), re);
210 }
211 }
212
213 private void createFilterPart(Composite parent) {
214 GridLayout layout = new GridLayout(2, false);
215 layout.marginWidth = layout.marginHeight = layout.verticalSpacing = 0;
216 layout.horizontalSpacing = 5;
217 parent.setLayout(layout);
218
219 // Text Area to filter
220 filterTxt = tk.createText(parent, "", SWT.BORDER | SWT.SINGLE
221 | SWT.SEARCH | SWT.CANCEL);
222 filterTxt.setMessage(FILTER_HELP_MSG);
223 filterTxt.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
224 filterTxt.addModifyListener(new ModifyListener() {
225 private static final long serialVersionUID = 8727389523069041623L;
226
227 public void modifyText(ModifyEvent event) {
228 refresh();
229 }
230 });
231
232 Button resetBtn = tk.createButton(parent, null, SWT.PUSH);
233 resetBtn.setImage(DistImages.IMG_REPO_READONLY);
234 resetBtn.addSelectionListener(new SelectionAdapter() {
235 private static final long serialVersionUID = -6523538838444581321L;
236
237 public void widgetSelected(SelectionEvent e) {
238 resetFilter();
239 }
240 });
241 }
242
243 private void resetFilter() {
244 filterTxt.setText("");
245 filterTxt.setMessage(FILTER_HELP_MSG);
246 }
247
248 private void createTableViewer(Composite parent) {
249 parent.setLayout(new FillLayout());
250 // helpers to enable sorting by column
251 List<String> propertiesList = new ArrayList<String>();
252 List<Integer> propertyTypesList = new ArrayList<Integer>();
253
254 // Define the TableViewer
255 viewer = new TableViewer(parent, SWT.SINGLE | SWT.H_SCROLL
256 | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
257
258 TableViewerColumn col;
259 // Name
260 // TableViewerColumn col = new TableViewerColumn(viewer, SWT.NONE);
261 // col.getColumn().setWidth(220);
262 // col.getColumn().setText("Category");
263 // col.setLabelProvider(new ColumnLabelProvider() {
264 // @Override
265 // public String getText(Object element) {
266 // return JcrUtils.get((Node) element, SlcNames.SLC_CATEGORY);
267 // }
268 // });
269 // col.getColumn().addSelectionListener(getSelectionAdapter(0));
270 // propertiesList.add(SlcNames.SLC_CATEGORY);
271 // propertyTypesList.add(PropertyType.STRING);
272
273 // Group base name
274 col = new TableViewerColumn(viewer, SWT.NONE);
275 col.getColumn().setWidth(220);
276 col.getColumn().setText("Group Name");
277 col.setLabelProvider(new ColumnLabelProvider() {
278 private static final long serialVersionUID = 6186787928630825293L;
279
280 @Override
281 public String getText(Object element) {
282 return JcrUtils.get((Node) element, SLC_GROUP_BASE_ID);
283 }
284 });
285 col.getColumn().addSelectionListener(getSelectionAdapter(0));
286 propertiesList.add(SLC_GROUP_BASE_ID);
287 propertyTypesList.add(PropertyType.STRING);
288
289 // Version
290 col = new TableViewerColumn(viewer, SWT.NONE);
291 col.getColumn().setWidth(80);
292 col.getColumn().setText("Has binaries");
293 col.setLabelProvider(new ColumnLabelProvider() {
294 private static final long serialVersionUID = -2017377132642062464L;
295
296 @Override
297 public String getText(Object element) {
298 try {
299 Node currNode = (Node) element;
300
301 return currNode.hasNode(RepoConstants.BINARIES_ARTIFACT_ID) ? "Yes"
302 : "No";
303 } catch (RepositoryException e) {
304 throw new SlcException("unable to check type of node "
305 + element, e);
306 }
307 }
308 });
309 // col.getColumn().addSelectionListener(getSelectionAdapter(2));
310 // propertiesList.add(SLC_VERSION);
311 // propertyTypesList.add(PropertyType.STRING);
312
313 final Table table = viewer.getTable();
314 table.setHeaderVisible(true);
315 table.setLinesVisible(true);
316
317 viewer.setContentProvider(new DistributionsContentProvider());
318 getSite().setSelectionProvider(viewer);
319
320 comparator = new DistNodeViewerComparator(0,
321 DistNodeViewerComparator.ASCENDING, propertiesList,
322 propertyTypesList);
323 viewer.setComparator(comparator);
324
325 // Context Menu
326 MenuManager menuManager = new MenuManager();
327 Menu menu = menuManager.createContextMenu(viewer.getTable());
328 menuManager.addMenuListener(new IMenuListener() {
329 private static final long serialVersionUID = 739004528695501335L;
330
331 public void menuAboutToShow(IMenuManager manager) {
332 contextMenuAboutToShow(manager);
333 }
334 });
335 viewer.getTable().setMenu(menu);
336 getSite().registerContextMenu(menuManager, viewer);
337
338 // Double click
339 viewer.addDoubleClickListener(new DoubleClickListener());
340 }
341
342 @Override
343 public void setFocus() {
344 viewer.getTable().setFocus();
345 }
346
347 /** Programmatically configure the context menu */
348 protected void contextMenuAboutToShow(IMenuManager menuManager) {
349 IWorkbenchWindow window = DistPlugin.getDefault().getWorkbench()
350 .getActiveWorkbenchWindow();
351 // Build conditions
352 // Mark as category base
353 Object firstElement = ((IStructuredSelection) viewer.getSelection())
354 .getFirstElement();
355 Node currSelected = (Node) firstElement;
356
357 DistWkspEditorInput input = (DistWkspEditorInput) getEditorInput();
358
359 Map<String, String> params = new HashMap<String, String>();
360 params.put(OpenGenerateBinariesWizard.PARAM_REPO_NODE_PATH,
361 input.getRepoNodePath());
362 try {
363 params.put(OpenGenerateBinariesWizard.PARAM_MODULE_PATH,
364 currSelected.getPath());
365 } catch (RepositoryException e) {
366 throw new SlcException("Unable to get path for " + currSelected, e);
367 }
368 params.put(OpenGenerateBinariesWizard.PARAM_WORKSPACE_NAME,
369 input.getWorkspaceName());
370
371 CommandUtils.refreshParameterizedCommand(menuManager, window,
372 OpenGenerateBinariesWizard.ID,
373 OpenGenerateBinariesWizard.DEFAULT_LABEL,
374 OpenGenerateBinariesWizard.DEFAULT_ICON, true, params);
375
376 // boolean isRelevant = false;
377 // try {
378 // isRelevant = currSelected.isNodeType(SlcTypes.SLC_CATEGORY);
379 // boolean canEdit = currSelected.canAddMixin(SlcTypes.SLC_CATEGORY);
380 //
381 // } catch (RepositoryException e) {
382 // throw new SlcException("unable to check type of node "
383 // + firstElement, e);
384 // }
385 // // Add
386 // if (isRelevant) {// Remove
387 // CommandUtils.refreshCommand(menuManager, window,
388 // MarkAsRelevantCategory.ID,
389 // MarkAsRelevantCategory.DEFAULT_REMOVE_LABEL,
390 // MarkAsRelevantCategory.DEFAULT_REMOVE_ICON, true);
391 // } else {
392 // CommandUtils.refreshCommand(menuManager, window,
393 // MarkAsRelevantCategory.ID,
394 // MarkAsRelevantCategory.DEFAULT_LABEL,
395 // MarkAsRelevantCategory.DEFAULT_ICON, true);
396 // }
397 }
398
399 private SelectionAdapter getSelectionAdapter(final int index) {
400 SelectionAdapter selectionAdapter = new SelectionAdapter() {
401 private static final long serialVersionUID = -1723894288128081757L;
402
403 @Override
404 public void widgetSelected(SelectionEvent e) {
405 Table table = viewer.getTable();
406 comparator.setColumn(index);
407 int dir = table.getSortDirection();
408 if (table.getSortColumn() == table.getColumn(index)) {
409 dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
410 } else {
411 dir = SWT.DOWN;
412 }
413 table.setSortDirection(dir);
414 table.setSortColumn(table.getColumn(index));
415 viewer.refresh();
416 }
417 };
418 return selectionAdapter;
419 }
420
421 /* LOCAL CLASSES */
422 private class DistributionsContentProvider implements
423 IStructuredContentProvider {
424 private static final long serialVersionUID = -5939763615620837492L;
425
426 // we keep a cache of the Nodes in the content provider to be able to
427 // manage long request
428 private List<Node> nodes;
429
430 public void dispose() {
431 }
432
433 // We expect a list of nodes as a new input
434 @SuppressWarnings("unchecked")
435 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
436 nodes = (List<Node>) newInput;
437 }
438
439 public Object[] getElements(Object arg0) {
440 return nodes.toArray();
441 }
442 }
443
444 private class DoubleClickListener implements IDoubleClickListener {
445
446 public void doubleClick(DoubleClickEvent event) {
447 Object obj = ((IStructuredSelection) event.getSelection())
448 .getFirstElement();
449 if (obj instanceof Node) {
450 Node node = (Node) obj;
451 try {
452 if (node.isNodeType(SlcTypes.SLC_ARTIFACT)) {
453 DistWkspEditorInput dwip = (DistWkspEditorInput) getEditorInput();
454 Map<String, String> params = new HashMap<String, String>();
455 params.put(OpenModuleEditor.PARAM_REPO_NODE_PATH,
456 dwip.getRepoNodePath());
457 params.put(OpenModuleEditor.PARAM_REPO_URI,
458 dwip.getUri());
459 params.put(OpenModuleEditor.PARAM_WORKSPACE_NAME,
460 dwip.getWorkspaceName());
461 String path = node.getPath();
462 params.put(OpenModuleEditor.PARAM_MODULE_PATH, path);
463 CommandUtils.callCommand(OpenModuleEditor.ID, params);
464 }
465 } catch (RepositoryException re) {
466 throw new SlcException("Cannot get path for node " + node
467 + " while setting parameters for "
468 + "command OpenModuleEditor", re);
469 }
470
471 }
472 }
473 }
474
475 class CategoryObserver extends AsyncUiEventListener {
476
477 public CategoryObserver(Display display) {
478 super(display);
479 }
480
481 @Override
482 protected Boolean willProcessInUiThread(List<Event> events)
483 throws RepositoryException {
484 for (Event event : events) {
485 String path = event.getPath();
486 if (JcrUtils.lastPathElement(path).equals(
487 DistConstants.JCR_MIXIN_TYPES))
488 return true;
489 }
490 return false;
491 }
492
493 protected void onEventInUiThread(List<Event> events)
494 throws RepositoryException {
495 if (getLog().isTraceEnabled())
496 getLog().trace("Refresh table");
497 viewer.refresh();
498 }
499 }
500
501 @Override
502 public void setActive(boolean active) {
503 super.setActive(active);
504 if (active) {
505 }
506 }
507 }