2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.slc
.client
.ui
.dist
.editors
;
18 import java
.util
.ArrayList
;
19 import java
.util
.HashMap
;
20 import java
.util
.List
;
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
;
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
.client
.ui
.dist
.DistConstants
;
43 import org
.argeo
.slc
.client
.ui
.dist
.DistImages
;
44 import org
.argeo
.slc
.client
.ui
.dist
.DistPlugin
;
45 import org
.argeo
.slc
.client
.ui
.dist
.commands
.OpenGenerateBinariesWizard
;
46 import org
.argeo
.slc
.client
.ui
.dist
.commands
.OpenModuleEditor
;
47 import org
.argeo
.slc
.client
.ui
.dist
.utils
.DistNodeViewerComparator
;
48 import org
.argeo
.slc
.jcr
.SlcNames
;
49 import org
.argeo
.slc
.jcr
.SlcTypes
;
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
;
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
89 public class WkspCategoryBaseListPage
extends FormPage
implements SlcNames
{
91 final static String PAGE_ID
= "WkspCategoryBaseListPage";
94 private Session session
;
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";
104 // private final static String[] observedTypes = { SlcTypes.SLC_GROUP_BASE
106 // private CategoryObserver categoriesObserver;
108 public WkspCategoryBaseListPage(FormEditor formEditor
, String title
,
110 super(formEditor
, PAGE_ID
, title
);
111 this.session
= session
;
115 protected void createFormContent(IManagedForm managedForm
) {
116 ScrolledForm form
= managedForm
.getForm();
117 tk
= managedForm
.getToolkit();
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
);
126 GridLayout layout
= new GridLayout(1, false);
127 Composite body
= form
.getBody();
128 body
.setLayout(layout
);
131 Composite header
= tk
.createComposite(body
);
132 header
.setLayoutData(new GridData(SWT
.FILL
, SWT
.TOP
, true, false));
133 createFilterPart(header
);
136 Composite tableCmp
= tk
.createComposite(body
);
137 tableCmp
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
138 createTableViewer(tableCmp
);
140 // categoriesObserver = new CategoryObserver(viewer.getTable()
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,
149 // } catch (RepositoryException e) {
150 // throw new SlcException("Cannot register listeners", e);
156 private void refresh() {
157 final List
<Node
> result
= JcrUtils
.nodeIteratorToList(listGroupBase());
158 viewer
.setInput(result
);
161 /** Build repository request */
162 private NodeIterator
listGroupBase() {
164 QueryManager queryManager
= session
.getWorkspace()
166 QueryObjectModelFactory factory
= queryManager
.getQOMFactory();
168 Selector source
= factory
.selector(SlcTypes
.SLC_GROUP_BASE
,
169 SlcTypes
.SLC_MODULE_COORDINATES
);
171 // Create a dynamic operand for each property on which we want to
173 DynamicOperand catDO
= factory
.propertyValue(
174 source
.getSelectorName(), SlcNames
.SLC_CATEGORY
);
175 DynamicOperand nameDO
= factory
.propertyValue(
176 source
.getSelectorName(), SlcNames
.SLC_NAME
);
178 String filter
= filterTxt
.getText();
180 Constraint defaultC
= null;
181 // Build constraints based the textArea content
182 if (filter
!= null && !"".equals(filter
.trim())) {
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
+ "%"));
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
));
195 if (defaultC
== null)
198 defaultC
= factory
.and(defaultC
, currC
);
202 QueryObjectModel query
= factory
.createQuery(source
, defaultC
,
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
);
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
);
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;
227 public void modifyText(ModifyEvent event
) {
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;
237 public void widgetSelected(SelectionEvent e
) {
243 private void resetFilter() {
244 filterTxt
.setText("");
245 filterTxt
.setMessage(FILTER_HELP_MSG
);
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
>();
254 // Define the TableViewer
255 viewer
= new TableViewer(parent
, SWT
.SINGLE
| SWT
.H_SCROLL
256 | SWT
.V_SCROLL
| SWT
.FULL_SELECTION
| SWT
.BORDER
);
258 TableViewerColumn col
;
260 // TableViewerColumn col = new TableViewerColumn(viewer, SWT.NONE);
261 // col.getColumn().setWidth(220);
262 // col.getColumn().setText("Category");
263 // col.setLabelProvider(new ColumnLabelProvider() {
265 // public String getText(Object element) {
266 // return JcrUtils.get((Node) element, SlcNames.SLC_CATEGORY);
269 // col.getColumn().addSelectionListener(getSelectionAdapter(0));
270 // propertiesList.add(SlcNames.SLC_CATEGORY);
271 // propertyTypesList.add(PropertyType.STRING);
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;
281 public String
getText(Object element
) {
282 return JcrUtils
.get((Node
) element
, SLC_GROUP_BASE_ID
);
285 col
.getColumn().addSelectionListener(getSelectionAdapter(0));
286 propertiesList
.add(SLC_GROUP_BASE_ID
);
287 propertyTypesList
.add(PropertyType
.STRING
);
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;
297 public String
getText(Object element
) {
299 Node currNode
= (Node
) element
;
301 return currNode
.hasNode(RepoConstants
.BINARIES_ARTIFACT_ID
) ?
"Yes"
303 } catch (RepositoryException e
) {
304 throw new SlcException("unable to check type of node "
309 // col.getColumn().addSelectionListener(getSelectionAdapter(2));
310 // propertiesList.add(SLC_VERSION);
311 // propertyTypesList.add(PropertyType.STRING);
313 final Table table
= viewer
.getTable();
314 table
.setHeaderVisible(true);
315 table
.setLinesVisible(true);
317 viewer
.setContentProvider(new DistributionsContentProvider());
318 getSite().setSelectionProvider(viewer
);
320 comparator
= new DistNodeViewerComparator(0,
321 DistNodeViewerComparator
.ASCENDING
, propertiesList
,
323 viewer
.setComparator(comparator
);
326 MenuManager menuManager
= new MenuManager();
327 Menu menu
= menuManager
.createContextMenu(viewer
.getTable());
328 menuManager
.addMenuListener(new IMenuListener() {
329 private static final long serialVersionUID
= 739004528695501335L;
331 public void menuAboutToShow(IMenuManager manager
) {
332 contextMenuAboutToShow(manager
);
335 viewer
.getTable().setMenu(menu
);
336 getSite().registerContextMenu(menuManager
, viewer
);
339 viewer
.addDoubleClickListener(new DoubleClickListener());
343 public void setFocus() {
344 viewer
.getTable().setFocus();
347 /** Programmatically configure the context menu */
348 protected void contextMenuAboutToShow(IMenuManager menuManager
) {
349 IWorkbenchWindow window
= DistPlugin
.getDefault().getWorkbench()
350 .getActiveWorkbenchWindow();
352 // Mark as category base
353 Object firstElement
= ((IStructuredSelection
) viewer
.getSelection())
355 Node currSelected
= (Node
) firstElement
;
357 DistWkspEditorInput input
= (DistWkspEditorInput
) getEditorInput();
359 Map
<String
, String
> params
= new HashMap
<String
, String
>();
360 params
.put(OpenGenerateBinariesWizard
.PARAM_REPO_NODE_PATH
,
361 input
.getRepoNodePath());
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
);
368 params
.put(OpenGenerateBinariesWizard
.PARAM_WORKSPACE_NAME
,
369 input
.getWorkspaceName());
371 CommandUtils
.refreshParameterizedCommand(menuManager
, window
,
372 OpenGenerateBinariesWizard
.ID
,
373 OpenGenerateBinariesWizard
.DEFAULT_LABEL
,
374 OpenGenerateBinariesWizard
.DEFAULT_ICON
, true, params
);
376 // boolean isRelevant = false;
378 // isRelevant = currSelected.isNodeType(SlcTypes.SLC_CATEGORY);
379 // boolean canEdit = currSelected.canAddMixin(SlcTypes.SLC_CATEGORY);
381 // } catch (RepositoryException e) {
382 // throw new SlcException("unable to check type of node "
383 // + firstElement, e);
386 // if (isRelevant) {// Remove
387 // CommandUtils.refreshCommand(menuManager, window,
388 // MarkAsRelevantCategory.ID,
389 // MarkAsRelevantCategory.DEFAULT_REMOVE_LABEL,
390 // MarkAsRelevantCategory.DEFAULT_REMOVE_ICON, true);
392 // CommandUtils.refreshCommand(menuManager, window,
393 // MarkAsRelevantCategory.ID,
394 // MarkAsRelevantCategory.DEFAULT_LABEL,
395 // MarkAsRelevantCategory.DEFAULT_ICON, true);
399 private SelectionAdapter
getSelectionAdapter(final int index
) {
400 SelectionAdapter selectionAdapter
= new SelectionAdapter() {
401 private static final long serialVersionUID
= -1723894288128081757L;
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
;
413 table
.setSortDirection(dir
);
414 table
.setSortColumn(table
.getColumn(index
));
418 return selectionAdapter
;
422 private class DistributionsContentProvider
implements
423 IStructuredContentProvider
{
424 private static final long serialVersionUID
= -5939763615620837492L;
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
;
430 public void dispose() {
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
;
439 public Object
[] getElements(Object arg0
) {
440 return nodes
.toArray();
444 private class DoubleClickListener
implements IDoubleClickListener
{
446 public void doubleClick(DoubleClickEvent event
) {
447 Object obj
= ((IStructuredSelection
) event
.getSelection())
449 if (obj
instanceof Node
) {
450 Node node
= (Node
) obj
;
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
,
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
);
465 } catch (RepositoryException re
) {
466 throw new SlcException("Cannot get path for node " + node
467 + " while setting parameters for "
468 + "command OpenModuleEditor", re
);
475 class CategoryObserver
extends AsyncUiEventListener
{
477 public CategoryObserver(Display display
) {
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
))
493 protected void onEventInUiThread(List
<Event
> events
)
494 throws RepositoryException
{
495 if (getLog().isTraceEnabled())
496 getLog().trace("Refresh table");
502 public void setActive(boolean active
) {
503 super.setActive(active
);