1 package org
.argeo
.slc
.client
.ui
.dist
.editors
;
3 import java
.util
.ArrayList
;
4 import java
.util
.HashMap
;
9 import javax
.jcr
.NodeIterator
;
10 import javax
.jcr
.PropertyType
;
11 import javax
.jcr
.RepositoryException
;
12 import javax
.jcr
.Session
;
13 import javax
.jcr
.observation
.Event
;
14 import javax
.jcr
.query
.QueryManager
;
15 import javax
.jcr
.query
.QueryResult
;
16 import javax
.jcr
.query
.qom
.Constraint
;
17 import javax
.jcr
.query
.qom
.DynamicOperand
;
18 import javax
.jcr
.query
.qom
.QueryObjectModel
;
19 import javax
.jcr
.query
.qom
.QueryObjectModelFactory
;
20 import javax
.jcr
.query
.qom
.Selector
;
21 import javax
.jcr
.query
.qom
.StaticOperand
;
23 import org
.argeo
.cms
.ui
.workbench
.util
.CommandUtils
;
24 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
25 import org
.argeo
.jcr
.JcrUtils
;
26 import org
.argeo
.slc
.SlcException
;
27 import org
.argeo
.slc
.SlcNames
;
28 import org
.argeo
.slc
.SlcTypes
;
29 import org
.argeo
.slc
.client
.ui
.dist
.DistConstants
;
30 import org
.argeo
.slc
.client
.ui
.dist
.DistImages
;
31 import org
.argeo
.slc
.client
.ui
.dist
.DistPlugin
;
32 import org
.argeo
.slc
.client
.ui
.dist
.commands
.OpenGenerateBinariesWizard
;
33 import org
.argeo
.slc
.client
.ui
.dist
.commands
.OpenModuleEditor
;
34 import org
.argeo
.slc
.client
.ui
.dist
.utils
.DistNodeViewerComparator
;
35 import org
.argeo
.slc
.repo
.RepoConstants
;
36 import org
.eclipse
.jface
.action
.IMenuListener
;
37 import org
.eclipse
.jface
.action
.IMenuManager
;
38 import org
.eclipse
.jface
.action
.MenuManager
;
39 import org
.eclipse
.jface
.dialogs
.IMessageProvider
;
40 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
41 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
42 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
43 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
44 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
45 import org
.eclipse
.jface
.viewers
.TableViewer
;
46 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
47 import org
.eclipse
.jface
.viewers
.Viewer
;
48 import org
.eclipse
.swt
.SWT
;
49 import org
.eclipse
.swt
.events
.ModifyEvent
;
50 import org
.eclipse
.swt
.events
.ModifyListener
;
51 import org
.eclipse
.swt
.events
.SelectionAdapter
;
52 import org
.eclipse
.swt
.events
.SelectionEvent
;
53 import org
.eclipse
.swt
.layout
.FillLayout
;
54 import org
.eclipse
.swt
.layout
.GridData
;
55 import org
.eclipse
.swt
.layout
.GridLayout
;
56 import org
.eclipse
.swt
.widgets
.Button
;
57 import org
.eclipse
.swt
.widgets
.Composite
;
58 import org
.eclipse
.swt
.widgets
.Display
;
59 import org
.eclipse
.swt
.widgets
.Menu
;
60 import org
.eclipse
.swt
.widgets
.Table
;
61 import org
.eclipse
.swt
.widgets
.Text
;
62 import org
.eclipse
.ui
.IWorkbenchWindow
;
63 import org
.eclipse
.ui
.forms
.IManagedForm
;
64 import org
.eclipse
.ui
.forms
.editor
.FormEditor
;
65 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
66 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
67 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
70 * Show all category base (currently only Aether group base) contained in a
71 * given workspace as filter-able table. Enable to definition of which of them
72 * should be managed as modular distribution
74 public class WkspCategoryBaseListPage
extends FormPage
implements SlcNames
{
76 final static String PAGE_ID
= "WkspCategoryBaseListPage";
79 private Session session
;
82 private DistNodeViewerComparator comparator
;
83 private TableViewer viewer
;
84 private FormToolkit tk
;
85 private Text filterTxt
;
86 private final static String FILTER_HELP_MSG
= "Enter filter criterion separated by a space";
89 // private final static String[] observedTypes = { SlcTypes.SLC_GROUP_BASE
91 // private CategoryObserver categoriesObserver;
93 public WkspCategoryBaseListPage(FormEditor formEditor
, String title
,
95 super(formEditor
, PAGE_ID
, title
);
96 this.session
= session
;
100 protected void createFormContent(IManagedForm managedForm
) {
101 ScrolledForm form
= managedForm
.getForm();
102 tk
= managedForm
.getToolkit();
104 form
.setText("Define Relevant Categories");
105 form
.setMessage("Choose in the below list "
106 + "the categories that can be used as base for "
107 + "modular distributions maintained via the current workspace",
108 IMessageProvider
.NONE
);
111 GridLayout layout
= new GridLayout(1, false);
112 Composite body
= form
.getBody();
113 body
.setLayout(layout
);
116 Composite header
= tk
.createComposite(body
);
117 header
.setLayoutData(new GridData(SWT
.FILL
, SWT
.TOP
, true, false));
118 createFilterPart(header
);
121 Composite tableCmp
= tk
.createComposite(body
);
122 tableCmp
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
123 createTableViewer(tableCmp
);
125 // categoriesObserver = new CategoryObserver(viewer.getTable()
128 // ObservationManager observationManager = session.getWorkspace()
129 // .getObservationManager();
130 // // FIXME Will not be notified if empty result is deleted
131 // observationManager.addEventListener(categoriesObserver,
132 // Event.PROPERTY_CHANGED, "/", true, null, observedTypes,
134 // } catch (RepositoryException e) {
135 // throw new SlcException("Cannot register listeners", e);
141 private void refresh() {
142 final List
<Node
> result
= JcrUtils
.nodeIteratorToList(listGroupBase());
143 viewer
.setInput(result
);
146 /** Build repository request */
147 private NodeIterator
listGroupBase() {
149 QueryManager queryManager
= session
.getWorkspace()
151 QueryObjectModelFactory factory
= queryManager
.getQOMFactory();
153 Selector source
= factory
.selector(SlcTypes
.SLC_GROUP_BASE
,
154 SlcTypes
.SLC_MODULE_COORDINATES
);
156 // Create a dynamic operand for each property on which we want to
158 DynamicOperand catDO
= factory
.propertyValue(
159 source
.getSelectorName(), SlcNames
.SLC_CATEGORY
);
160 DynamicOperand nameDO
= factory
.propertyValue(
161 source
.getSelectorName(), SlcNames
.SLC_NAME
);
163 String filter
= filterTxt
.getText();
165 Constraint defaultC
= null;
166 // Build constraints based the textArea content
167 if (filter
!= null && !"".equals(filter
.trim())) {
169 String
[] strs
= filter
.trim().split(" ");
170 for (String token
: strs
) {
171 token
= token
.replace('*', '%');
172 StaticOperand so
= factory
.literal(session
173 .getValueFactory().createValue("%" + token
+ "%"));
175 Constraint currC
= factory
.comparison(catDO
,
176 QueryObjectModelFactory
.JCR_OPERATOR_LIKE
, so
);
177 currC
= factory
.or(currC
, factory
.comparison(nameDO
,
178 QueryObjectModelFactory
.JCR_OPERATOR_LIKE
, so
));
180 if (defaultC
== null)
183 defaultC
= factory
.and(defaultC
, currC
);
187 QueryObjectModel query
= factory
.createQuery(source
, defaultC
,
189 QueryResult result
= query
.execute();
190 return result
.getNodes();
191 } catch (RepositoryException re
) {
192 throw new SlcException(
193 "Unable to refresh group list for workspace "
194 + getEditorInput().getName(), re
);
198 private void createFilterPart(Composite parent
) {
199 GridLayout layout
= new GridLayout(2, false);
200 layout
.marginWidth
= layout
.marginHeight
= layout
.verticalSpacing
= 0;
201 layout
.horizontalSpacing
= 5;
202 parent
.setLayout(layout
);
204 // Text Area to filter
205 filterTxt
= tk
.createText(parent
, "", SWT
.BORDER
| SWT
.SINGLE
206 | SWT
.SEARCH
| SWT
.CANCEL
);
207 filterTxt
.setMessage(FILTER_HELP_MSG
);
208 filterTxt
.setLayoutData(new GridData(SWT
.FILL
, SWT
.TOP
, true, false));
209 filterTxt
.addModifyListener(new ModifyListener() {
210 private static final long serialVersionUID
= 8727389523069041623L;
212 public void modifyText(ModifyEvent event
) {
217 Button resetBtn
= tk
.createButton(parent
, null, SWT
.PUSH
);
218 resetBtn
.setImage(DistImages
.IMG_REPO_READONLY
);
219 resetBtn
.addSelectionListener(new SelectionAdapter() {
220 private static final long serialVersionUID
= -6523538838444581321L;
222 public void widgetSelected(SelectionEvent e
) {
228 private void resetFilter() {
229 filterTxt
.setText("");
230 filterTxt
.setMessage(FILTER_HELP_MSG
);
233 private void createTableViewer(Composite parent
) {
234 parent
.setLayout(new FillLayout());
235 // helpers to enable sorting by column
236 List
<String
> propertiesList
= new ArrayList
<String
>();
237 List
<Integer
> propertyTypesList
= new ArrayList
<Integer
>();
239 // Define the TableViewer
240 viewer
= new TableViewer(parent
, SWT
.SINGLE
| SWT
.H_SCROLL
241 | SWT
.V_SCROLL
| SWT
.FULL_SELECTION
| SWT
.BORDER
);
243 TableViewerColumn col
;
245 // TableViewerColumn col = new TableViewerColumn(viewer, SWT.NONE);
246 // col.getColumn().setWidth(220);
247 // col.getColumn().setText("Category");
248 // col.setLabelProvider(new ColumnLabelProvider() {
250 // public String getText(Object element) {
251 // return JcrUtils.get((Node) element, SlcNames.SLC_CATEGORY);
254 // col.getColumn().addSelectionListener(getSelectionAdapter(0));
255 // propertiesList.add(SlcNames.SLC_CATEGORY);
256 // propertyTypesList.add(PropertyType.STRING);
259 col
= new TableViewerColumn(viewer
, SWT
.NONE
);
260 col
.getColumn().setWidth(220);
261 col
.getColumn().setText("Group Name");
262 col
.setLabelProvider(new ColumnLabelProvider() {
263 private static final long serialVersionUID
= 6186787928630825293L;
266 public String
getText(Object element
) {
267 return JcrUtils
.get((Node
) element
, SLC_GROUP_BASE_ID
);
270 col
.getColumn().addSelectionListener(getSelectionAdapter(0));
271 propertiesList
.add(SLC_GROUP_BASE_ID
);
272 propertyTypesList
.add(PropertyType
.STRING
);
275 col
= new TableViewerColumn(viewer
, SWT
.NONE
);
276 col
.getColumn().setWidth(80);
277 col
.getColumn().setText("Has binaries");
278 col
.setLabelProvider(new ColumnLabelProvider() {
279 private static final long serialVersionUID
= -2017377132642062464L;
282 public String
getText(Object element
) {
284 Node currNode
= (Node
) element
;
286 return currNode
.hasNode(RepoConstants
.BINARIES_ARTIFACT_ID
) ?
"Yes"
288 } catch (RepositoryException e
) {
289 throw new SlcException("unable to check type of node "
294 // col.getColumn().addSelectionListener(getSelectionAdapter(2));
295 // propertiesList.add(SLC_VERSION);
296 // propertyTypesList.add(PropertyType.STRING);
298 final Table table
= viewer
.getTable();
299 table
.setHeaderVisible(true);
300 table
.setLinesVisible(true);
302 viewer
.setContentProvider(new DistributionsContentProvider());
303 getSite().setSelectionProvider(viewer
);
305 comparator
= new DistNodeViewerComparator(0,
306 DistNodeViewerComparator
.ASCENDING
, propertiesList
,
308 viewer
.setComparator(comparator
);
311 MenuManager menuManager
= new MenuManager();
312 Menu menu
= menuManager
.createContextMenu(viewer
.getTable());
313 menuManager
.addMenuListener(new IMenuListener() {
314 private static final long serialVersionUID
= 739004528695501335L;
316 public void menuAboutToShow(IMenuManager manager
) {
317 contextMenuAboutToShow(manager
);
320 viewer
.getTable().setMenu(menu
);
321 getSite().registerContextMenu(menuManager
, viewer
);
324 viewer
.addDoubleClickListener(new DoubleClickListener());
328 public void setFocus() {
329 viewer
.getTable().setFocus();
332 /** Programmatically configure the context menu */
333 protected void contextMenuAboutToShow(IMenuManager menuManager
) {
334 IWorkbenchWindow window
= DistPlugin
.getDefault().getWorkbench()
335 .getActiveWorkbenchWindow();
337 // Mark as category base
338 Object firstElement
= ((IStructuredSelection
) viewer
.getSelection())
340 Node currSelected
= (Node
) firstElement
;
342 DistWkspEditorInput input
= (DistWkspEditorInput
) getEditorInput();
344 Map
<String
, String
> params
= new HashMap
<String
, String
>();
345 params
.put(OpenGenerateBinariesWizard
.PARAM_REPO_NODE_PATH
,
346 input
.getRepoNodePath());
348 params
.put(OpenGenerateBinariesWizard
.PARAM_MODULE_PATH
,
349 currSelected
.getPath());
350 } catch (RepositoryException e
) {
351 throw new SlcException("Unable to get path for " + currSelected
, e
);
353 params
.put(OpenGenerateBinariesWizard
.PARAM_WORKSPACE_NAME
,
354 input
.getWorkspaceName());
356 CommandUtils
.refreshParameterizedCommand(menuManager
, window
,
357 OpenGenerateBinariesWizard
.ID
,
358 OpenGenerateBinariesWizard
.DEFAULT_LABEL
,
359 OpenGenerateBinariesWizard
.DEFAULT_ICON
, true, params
);
361 // boolean isRelevant = false;
363 // isRelevant = currSelected.isNodeType(SlcTypes.SLC_CATEGORY);
364 // boolean canEdit = currSelected.canAddMixin(SlcTypes.SLC_CATEGORY);
366 // } catch (RepositoryException e) {
367 // throw new SlcException("unable to check type of node "
368 // + firstElement, e);
371 // if (isRelevant) {// Remove
372 // CommandUtils.refreshCommand(menuManager, window,
373 // MarkAsRelevantCategory.ID,
374 // MarkAsRelevantCategory.DEFAULT_REMOVE_LABEL,
375 // MarkAsRelevantCategory.DEFAULT_REMOVE_ICON, true);
377 // CommandUtils.refreshCommand(menuManager, window,
378 // MarkAsRelevantCategory.ID,
379 // MarkAsRelevantCategory.DEFAULT_LABEL,
380 // MarkAsRelevantCategory.DEFAULT_ICON, true);
384 private SelectionAdapter
getSelectionAdapter(final int index
) {
385 SelectionAdapter selectionAdapter
= new SelectionAdapter() {
386 private static final long serialVersionUID
= -1723894288128081757L;
389 public void widgetSelected(SelectionEvent e
) {
390 Table table
= viewer
.getTable();
391 comparator
.setColumn(index
);
392 int dir
= table
.getSortDirection();
393 if (table
.getSortColumn() == table
.getColumn(index
)) {
394 dir
= dir
== SWT
.UP ? SWT
.DOWN
: SWT
.UP
;
398 table
.setSortDirection(dir
);
399 table
.setSortColumn(table
.getColumn(index
));
403 return selectionAdapter
;
407 private class DistributionsContentProvider
implements
408 IStructuredContentProvider
{
409 private static final long serialVersionUID
= -5939763615620837492L;
411 // we keep a cache of the Nodes in the content provider to be able to
412 // manage long request
413 private List
<Node
> nodes
;
415 public void dispose() {
418 // We expect a list of nodes as a new input
419 @SuppressWarnings("unchecked")
420 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
421 nodes
= (List
<Node
>) newInput
;
424 public Object
[] getElements(Object arg0
) {
425 return nodes
.toArray();
429 private class DoubleClickListener
implements IDoubleClickListener
{
431 public void doubleClick(DoubleClickEvent event
) {
432 Object obj
= ((IStructuredSelection
) event
.getSelection())
434 if (obj
instanceof Node
) {
435 Node node
= (Node
) obj
;
437 if (node
.isNodeType(SlcTypes
.SLC_ARTIFACT
)) {
438 DistWkspEditorInput dwip
= (DistWkspEditorInput
) getEditorInput();
439 Map
<String
, String
> params
= new HashMap
<String
, String
>();
440 params
.put(OpenModuleEditor
.PARAM_REPO_NODE_PATH
,
441 dwip
.getRepoNodePath());
442 params
.put(OpenModuleEditor
.PARAM_REPO_URI
,
444 params
.put(OpenModuleEditor
.PARAM_WORKSPACE_NAME
,
445 dwip
.getWorkspaceName());
446 String path
= node
.getPath();
447 params
.put(OpenModuleEditor
.PARAM_MODULE_PATH
, path
);
448 CommandUtils
.callCommand(OpenModuleEditor
.ID
, params
);
450 } catch (RepositoryException re
) {
451 throw new SlcException("Cannot get path for node " + node
452 + " while setting parameters for "
453 + "command OpenModuleEditor", re
);
460 class CategoryObserver
extends AsyncUiEventListener
{
462 public CategoryObserver(Display display
) {
467 protected Boolean
willProcessInUiThread(List
<Event
> events
)
468 throws RepositoryException
{
469 for (Event event
: events
) {
470 String path
= event
.getPath();
471 if (JcrUtils
.lastPathElement(path
).equals(
472 DistConstants
.JCR_MIXIN_TYPES
))
478 protected void onEventInUiThread(List
<Event
> events
)
479 throws RepositoryException
{
480 if (getLog().isTraceEnabled())
481 getLog().trace("Refresh table");
487 public void setActive(boolean active
) {
488 super.setActive(active
);