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
.List
;
21 import javax
.jcr
.Node
;
22 import javax
.jcr
.NodeIterator
;
23 import javax
.jcr
.PropertyType
;
24 import javax
.jcr
.RepositoryException
;
25 import javax
.jcr
.Session
;
26 import javax
.jcr
.query
.QueryManager
;
27 import javax
.jcr
.query
.QueryResult
;
28 import javax
.jcr
.query
.qom
.Constraint
;
29 import javax
.jcr
.query
.qom
.DynamicOperand
;
30 import javax
.jcr
.query
.qom
.Ordering
;
31 import javax
.jcr
.query
.qom
.QueryObjectModel
;
32 import javax
.jcr
.query
.qom
.QueryObjectModelFactory
;
33 import javax
.jcr
.query
.qom
.Selector
;
34 import javax
.jcr
.query
.qom
.StaticOperand
;
36 import org
.argeo
.ArgeoException
;
37 import org
.argeo
.eclipse
.ui
.ErrorFeedback
;
38 import org
.argeo
.jcr
.JcrUtils
;
39 import org
.argeo
.slc
.client
.ui
.dist
.DistConstants
;
40 import org
.argeo
.slc
.client
.ui
.dist
.DistImages
;
41 import org
.argeo
.slc
.client
.ui
.dist
.DistPlugin
;
42 import org
.argeo
.slc
.client
.ui
.dist
.commands
.DeleteArtifacts
;
43 import org
.argeo
.slc
.client
.ui
.dist
.utils
.CommandHelpers
;
44 import org
.argeo
.slc
.client
.ui
.dist
.utils
.NodeViewerComparator
;
45 import org
.argeo
.slc
.jcr
.SlcNames
;
46 import org
.argeo
.slc
.jcr
.SlcTypes
;
47 import org
.eclipse
.jface
.action
.IMenuListener
;
48 import org
.eclipse
.jface
.action
.IMenuManager
;
49 import org
.eclipse
.jface
.action
.MenuManager
;
50 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
51 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
52 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
53 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
54 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
55 import org
.eclipse
.jface
.viewers
.TableViewer
;
56 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
57 import org
.eclipse
.jface
.viewers
.Viewer
;
58 import org
.eclipse
.swt
.SWT
;
59 import org
.eclipse
.swt
.events
.ControlEvent
;
60 import org
.eclipse
.swt
.events
.ControlListener
;
61 import org
.eclipse
.swt
.events
.ModifyEvent
;
62 import org
.eclipse
.swt
.events
.ModifyListener
;
63 import org
.eclipse
.swt
.events
.SelectionAdapter
;
64 import org
.eclipse
.swt
.events
.SelectionEvent
;
65 import org
.eclipse
.swt
.events
.SelectionListener
;
66 import org
.eclipse
.swt
.layout
.GridData
;
67 import org
.eclipse
.swt
.layout
.GridLayout
;
68 import org
.eclipse
.swt
.widgets
.Button
;
69 import org
.eclipse
.swt
.widgets
.Composite
;
70 import org
.eclipse
.swt
.widgets
.Label
;
71 import org
.eclipse
.swt
.widgets
.Menu
;
72 import org
.eclipse
.swt
.widgets
.Table
;
73 import org
.eclipse
.swt
.widgets
.Text
;
74 import org
.eclipse
.ui
.IWorkbenchWindow
;
75 import org
.eclipse
.ui
.PartInitException
;
76 import org
.eclipse
.ui
.forms
.IManagedForm
;
77 import org
.eclipse
.ui
.forms
.editor
.FormEditor
;
78 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
79 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
80 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
82 /** Table giving an overview of an OSGi distribution with corresponding filters */
83 public class DistributionOverviewPage
extends FormPage
implements SlcNames
{
84 final static String PAGE_ID
= "distributionOverviewPage";
85 // final private static Log log = LogFactory
86 // .getLog(DistributionOverviewPage.class);
89 private Session session
;
92 private NodeViewerComparator comparator
;
93 private TableViewer viewer
;
94 private Text artifactTxt
;
95 private FormToolkit tk
;
96 private Composite header
;
98 // private Section headerSection;
100 public DistributionOverviewPage(FormEditor formEditor
, String title
,
102 super(formEditor
, PAGE_ID
, title
);
103 this.session
= session
;
107 protected void createFormContent(IManagedForm managedForm
) {
108 ScrolledForm form
= managedForm
.getForm();
109 tk
= managedForm
.getToolkit();
112 GridLayout layout
= new GridLayout(1, false);
113 Composite body
= form
.getBody();
114 body
.setLayout(layout
);
116 // Add the filter section
117 createFilterPart(body
);
119 createTableViewer(body
);
121 viewer
.setInput(session
);
124 // Add a listener to enable custom resize process
125 form
.addControlListener(new ControlListener() {
126 public void controlResized(ControlEvent e
) {
130 public void controlMoved(ControlEvent e
) {
134 // This below doesn not work; the listener must be added as a control
135 // listener to be correctly notified when resize events happen
137 // form.addListener(SWT.RESIZE, new Listener() {
138 // public void handleEvent(Event event) {
139 // log.debug("Form resized ....");
145 /** Build repository request */
146 private NodeIterator
listBundleArtifacts(Session session
)
147 throws RepositoryException
{
148 QueryManager queryManager
= session
.getWorkspace().getQueryManager();
149 QueryObjectModelFactory factory
= queryManager
.getQOMFactory();
151 final String bundleArtifactsSelector
= "bundleArtifacts";
152 Selector source
= factory
.selector(SlcTypes
.SLC_BUNDLE_ARTIFACT
,
153 bundleArtifactsSelector
);
155 // Create a dynamic operand for each property on which we want to filter
156 DynamicOperand symbNameDO
= factory
.propertyValue(
157 source
.getSelectorName(), SlcNames
.SLC_SYMBOLIC_NAME
);
158 DynamicOperand versionDO
= factory
.propertyValue(
159 source
.getSelectorName(), SlcNames
.SLC_BUNDLE_VERSION
);
160 DynamicOperand nameDO
= factory
.propertyValue(source
.getSelectorName(),
161 DistConstants
.SLC_BUNDLE_NAME
);
163 // Default Constraint: no source artifacts
164 Constraint defaultC
= factory
.not(factory
.comparison(
166 QueryObjectModelFactory
.JCR_OPERATOR_LIKE
,
167 factory
.literal(session
.getValueFactory().createValue(
170 // Build constraints based the textArea content
171 String artifactTxtVal
= artifactTxt
.getText();
172 if (!"".equals(artifactTxtVal
.trim())) {
174 String
[] strs
= artifactTxtVal
.trim().split(" ");
175 for (String token
: strs
) {
176 token
= token
.replace('*', '%');
177 StaticOperand so
= factory
.literal(session
.getValueFactory()
178 .createValue("%" + token
+ "%"));
180 Constraint currC
= factory
.comparison(symbNameDO
,
181 QueryObjectModelFactory
.JCR_OPERATOR_LIKE
, so
);
182 currC
= factory
.or(currC
, factory
.comparison(versionDO
,
183 QueryObjectModelFactory
.JCR_OPERATOR_LIKE
, so
));
184 currC
= factory
.or(currC
, factory
.comparison(nameDO
,
185 QueryObjectModelFactory
.JCR_OPERATOR_LIKE
, so
));
187 defaultC
= factory
.and(defaultC
, currC
);
191 Ordering order
= factory
.descending(factory
.propertyValue(
192 bundleArtifactsSelector
, SlcNames
.SLC_BUNDLE_VERSION
));
193 Ordering order2
= factory
.ascending(factory
.propertyValue(
194 bundleArtifactsSelector
, SlcNames
.SLC_SYMBOLIC_NAME
));
195 Ordering
[] orderings
= { order
, order2
};
197 QueryObjectModel query
= factory
.createQuery(source
, defaultC
,
200 QueryResult result
= query
.execute();
201 return result
.getNodes();
205 private void createFilterPart(Composite parent
) {
206 header
= tk
.createComposite(parent
);
207 GridLayout layout
= new GridLayout(2, false);
208 header
.setLayout(layout
);
209 GridData gd
= new GridData(SWT
.FILL
, SWT
.FILL
, false, false);
210 header
.setLayoutData(gd
);
212 // Title: some meta information
213 String desc
= ((DistributionEditorInput
) getEditorInput())
214 .getRepositoryDescription();
215 Label lbl
= tk
.createLabel(header
, desc
, SWT
.NONE
);
217 gd
= new GridData(SWT
.FILL
, SWT
.FILL
, false, false);
218 gd
.horizontalSpan
= 2;
219 lbl
.setLayoutData(gd
);
221 // Text Area to filter
222 artifactTxt
= tk
.createText(header
, "", SWT
.BORDER
| SWT
.SINGLE
);
223 gd
= new GridData(SWT
.FILL
, SWT
.FILL
, false, false);
224 gd
.grabExcessHorizontalSpace
= true;
225 artifactTxt
.setLayoutData(gd
);
226 artifactTxt
.addModifyListener(new ModifyListener() {
228 public void modifyText(ModifyEvent event
) {
229 refreshFilteredList();
233 Button resetBtn
= tk
.createButton(header
, null, SWT
.PUSH
);
234 resetBtn
.setImage(DistImages
.IMG_REPO_READONLY
);
235 resetBtn
.addSelectionListener(new SelectionListener() {
237 public void widgetSelected(SelectionEvent e
) {
241 public void widgetDefaultSelected(SelectionEvent e
) {
247 private void resetFilter() {
248 artifactTxt
.setText("");
249 artifactTxt
.setMessage("Enter filter criterion separated by a space");
253 private void refreshFilteredList() {
257 private void createTableViewer(Composite parent
) {
258 // helpers to enable sorting by column
259 List
<String
> propertiesList
= new ArrayList
<String
>();
260 List
<Integer
> propertyTypesList
= new ArrayList
<Integer
>();
262 // Define the TableViewer
263 viewer
= new TableViewer(parent
, SWT
.MULTI
| SWT
.H_SCROLL
264 | SWT
.V_SCROLL
| SWT
.FULL_SELECTION
| SWT
.BORDER
);
267 TableViewerColumn col
= new TableViewerColumn(viewer
, SWT
.NONE
);
268 col
.getColumn().setWidth(300);
269 col
.getColumn().setText("Name");
270 col
.setLabelProvider(new ColumnLabelProvider() {
272 public String
getText(Object element
) {
273 return JcrUtils
.get((Node
) element
,
274 DistConstants
.SLC_BUNDLE_NAME
);
277 col
.getColumn().addSelectionListener(getSelectionAdapter(0));
278 propertiesList
.add(DistConstants
.SLC_BUNDLE_NAME
);
279 propertyTypesList
.add(PropertyType
.STRING
);
282 col
= new TableViewerColumn(viewer
, SWT
.V_SCROLL
);
283 col
.getColumn().setWidth(300);
284 col
.getColumn().setText("Symbolic name");
285 col
.setLabelProvider(new ColumnLabelProvider() {
287 public String
getText(Object element
) {
288 return JcrUtils
.get((Node
) element
, SLC_SYMBOLIC_NAME
);
291 col
.getColumn().addSelectionListener(getSelectionAdapter(1));
292 propertiesList
.add(SLC_SYMBOLIC_NAME
);
293 propertyTypesList
.add(PropertyType
.STRING
);
296 col
= new TableViewerColumn(viewer
, SWT
.NONE
);
297 col
.getColumn().setWidth(100);
298 col
.getColumn().setText("Version");
299 col
.setLabelProvider(new ColumnLabelProvider() {
301 public String
getText(Object element
) {
302 return JcrUtils
.get((Node
) element
, SLC_BUNDLE_VERSION
);
305 col
.getColumn().addSelectionListener(getSelectionAdapter(2));
306 propertiesList
.add(SLC_BUNDLE_VERSION
);
307 propertyTypesList
.add(PropertyType
.STRING
);
309 final Table table
= viewer
.getTable();
310 table
.setHeaderVisible(true);
311 table
.setLinesVisible(true);
313 viewer
.setContentProvider(new DistributionsContentProvider());
314 getSite().setSelectionProvider(viewer
);
316 comparator
= new NodeViewerComparator(2,
317 NodeViewerComparator
.ASCENDING
, propertiesList
,
319 viewer
.setComparator(comparator
);
322 MenuManager menuManager
= new MenuManager();
323 Menu menu
= menuManager
.createContextMenu(viewer
.getTable());
324 menuManager
.addMenuListener(new IMenuListener() {
325 public void menuAboutToShow(IMenuManager manager
) {
326 contextMenuAboutToShow(manager
);
329 viewer
.getTable().setMenu(menu
);
330 getSite().registerContextMenu(menuManager
, viewer
);
333 viewer
.addDoubleClickListener(new DoubleClickListener());
337 public void setFocus() {
338 viewer
.getTable().setFocus();
341 /** force refresh of the artifact list */
342 public void refresh() {
346 /** Programmatically configure the context menu */
347 protected void contextMenuAboutToShow(IMenuManager menuManager
) {
348 IWorkbenchWindow window
= DistPlugin
.getDefault().getWorkbench()
349 .getActiveWorkbenchWindow();
353 // Delete selected artifacts
354 CommandHelpers
.refreshCommand(menuManager
, window
, DeleteArtifacts
.ID
,
355 DeleteArtifacts
.DEFAULT_LABEL
,
356 DeleteArtifacts
.DEFAULT_ICON_PATH
, true);
360 private SelectionAdapter
getSelectionAdapter(final int index
) {
361 SelectionAdapter selectionAdapter
= new SelectionAdapter() {
363 public void widgetSelected(SelectionEvent e
) {
364 Table table
= viewer
.getTable();
365 comparator
.setColumn(index
);
366 int dir
= table
.getSortDirection();
367 if (table
.getSortColumn() == table
.getColumn(index
)) {
368 dir
= dir
== SWT
.UP ? SWT
.DOWN
: SWT
.UP
;
372 table
.setSortDirection(dir
);
373 table
.setSortColumn(table
.getColumn(index
));
377 return selectionAdapter
;
381 private class DistributionsContentProvider
implements
382 IStructuredContentProvider
{
383 // private Session session;
385 public void dispose() {
388 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
389 // session = (Session) newInput;
392 public Object
[] getElements(Object arg0
) {
394 List
<Node
> nodes
= JcrUtils
395 .nodeIteratorToList(listBundleArtifacts(session
));
396 return nodes
.toArray();
397 } catch (RepositoryException e
) {
398 ErrorFeedback
.show("Cannot list bundles", e
);
404 private class DoubleClickListener
implements IDoubleClickListener
{
406 public void doubleClick(DoubleClickEvent event
) {
407 Object obj
= ((IStructuredSelection
) event
.getSelection())
410 if (obj
instanceof Node
) {
411 Node node
= (Node
) obj
;
412 if (node
.isNodeType(SlcTypes
.SLC_BUNDLE_ARTIFACT
)) {
413 GenericBundleEditorInput gaei
= new GenericBundleEditorInput(
415 DistPlugin
.getDefault().getWorkbench()
416 .getActiveWorkbenchWindow().getActivePage()
417 .openEditor(gaei
, GenericBundleEditor
.ID
);
420 } catch (RepositoryException re
) {
421 throw new ArgeoException(
422 "Repository error while getting node info", re
);
423 } catch (PartInitException pie
) {
424 throw new ArgeoException(
425 "Unexepected exception while opening artifact editor",
432 * UI Trick to put scroll bar on the table rather than on the scrollform
434 private void refreshLayout() {
435 // Compute desired table size
436 int maxH
= getManagedForm().getForm().getSize().y
;
437 int maxW
= getManagedForm().getForm().getParent().getSize().x
;
438 maxH
= maxH
- header
.getSize().y
;
439 final Table table
= viewer
.getTable();
440 GridData gd
= new GridData(SWT
.LEFT
, SWT
.TOP
, true, true);
442 // when table height is less than 200 px, we let the scroll bar on the
444 // FIXME substract some spare space. Here is room for optimization
445 gd
.heightHint
= Math
.max(maxH
- 35, 200);
446 gd
.widthHint
= Math
.max(maxW
- 35, 200);
448 table
.setLayoutData(gd
);
449 getManagedForm().reflow(true);
453 public void setActive(boolean active
) {
454 super.setActive(active
);