]> git.argeo.org Git - gpl/argeo-slc.git/blob - plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java
Update decorators to show more explicitly PASSED / FAILED / ERROR status in the Resul...
[gpl/argeo-slc.git] / plugins / org.argeo.slc.client.ui / src / main / java / org / argeo / slc / client / ui / views / JcrExecutionModulesView.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.views;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Comparator;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.SortedSet;
24 import java.util.TreeSet;
25
26 import javax.jcr.Node;
27 import javax.jcr.NodeIterator;
28 import javax.jcr.Property;
29 import javax.jcr.RepositoryException;
30 import javax.jcr.Session;
31 import javax.jcr.nodetype.NodeType;
32 import javax.jcr.observation.Event;
33 import javax.jcr.query.Query;
34 import javax.jcr.query.QueryManager;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.argeo.ArgeoException;
39 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
40 import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider;
41 import org.argeo.eclipse.ui.jcr.NodeElementComparer;
42 import org.argeo.eclipse.ui.jcr.SimpleNodeContentProvider;
43 import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
44 import org.argeo.slc.SlcException;
45 import org.argeo.slc.client.ui.ClientUiPlugin;
46 import org.argeo.slc.client.ui.SlcImages;
47 import org.argeo.slc.client.ui.editors.ProcessEditor;
48 import org.argeo.slc.client.ui.editors.ProcessEditorInput;
49 import org.argeo.slc.execution.ExecutionModulesManager;
50 import org.argeo.slc.jcr.SlcJcrConstants;
51 import org.argeo.slc.jcr.SlcNames;
52 import org.argeo.slc.jcr.SlcTypes;
53 import org.eclipse.jface.action.Action;
54 import org.eclipse.jface.action.IMenuListener;
55 import org.eclipse.jface.action.IMenuManager;
56 import org.eclipse.jface.action.MenuManager;
57 import org.eclipse.jface.viewers.DoubleClickEvent;
58 import org.eclipse.jface.viewers.IDoubleClickListener;
59 import org.eclipse.jface.viewers.IStructuredSelection;
60 import org.eclipse.jface.viewers.ITableLabelProvider;
61 import org.eclipse.jface.viewers.TreeViewer;
62 import org.eclipse.swt.SWT;
63 import org.eclipse.swt.dnd.DND;
64 import org.eclipse.swt.dnd.DragSourceAdapter;
65 import org.eclipse.swt.dnd.DragSourceEvent;
66 import org.eclipse.swt.dnd.TextTransfer;
67 import org.eclipse.swt.dnd.Transfer;
68 import org.eclipse.swt.graphics.Image;
69 import org.eclipse.swt.widgets.Composite;
70 import org.eclipse.swt.widgets.Display;
71 import org.eclipse.swt.widgets.Menu;
72 import org.eclipse.ui.IWorkbenchPage;
73 import org.eclipse.ui.PlatformUI;
74 import org.eclipse.ui.part.ViewPart;
75
76 /** JCR based view of the execution modules. */
77 public class JcrExecutionModulesView extends ViewPart implements SlcTypes,
78 SlcNames {
79 private final static Log log = LogFactory
80 .getLog(JcrExecutionModulesView.class);
81
82 public static final String ID = ClientUiPlugin.ID
83 + ".jcrExecutionModulesView";
84
85 private TreeViewer viewer;
86
87 /* DEPENDENCY INJECTION */
88 private Session session;
89 private ExecutionModulesManager modulesManager;
90
91 public void createPartControl(Composite parent) {
92 viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
93 EclipseUiSpecificUtils.enableToolTipSupport(viewer);
94 ViewContentProvider contentProvider = new ViewContentProvider(session);
95 viewer.setContentProvider(contentProvider);
96 viewer.setComparer(new NodeElementComparer());
97 final ViewLabelProvider viewLabelProvider = new ViewLabelProvider();
98 viewer.setLabelProvider(viewLabelProvider);
99 viewer.setInput(getViewSite());
100 viewer.addDoubleClickListener(new ViewDoubleClickListener());
101 // context menu
102 addContextMenu(viewer);
103
104 getViewSite().setSelectionProvider(viewer);
105
106 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
107 // Transfer[] tt = new Transfer[] { EditorInputTransfer.getInstance() };
108 int operations = DND.DROP_COPY | DND.DROP_MOVE;
109 viewer.addDragSupport(operations, tt, new ViewDragListener());
110
111 try {
112 String[] nodeTypes = { SlcTypes.SLC_AGENT,
113 SlcTypes.SLC_AGENT_FACTORY, SlcTypes.SLC_EXECUTION_MODULE };
114 session.getWorkspace()
115 .getObservationManager()
116 .addEventListener(
117 new VmAgentObserver(viewer.getTree().getDisplay()),
118 Event.NODE_ADDED | Event.NODE_REMOVED
119 | Event.NODE_MOVED,
120 SlcJcrConstants.VM_AGENT_FACTORY_PATH, true, null,
121 nodeTypes, false);
122 } catch (RepositoryException e) {
123 throw new SlcException("Cannot add observer", e);
124 }
125 }
126
127 public void setFocus() {
128 viewer.getControl().setFocus();
129 }
130
131 public TreeViewer getViewer() {
132 return viewer;
133 }
134
135 public void refreshView() {
136 viewer.setInput(getViewSite());
137 }
138
139 // Controllers
140 class ViewContentProvider extends SimpleNodeContentProvider {
141
142 public ViewContentProvider(Session session) {
143 super(session,
144 new String[] { SlcJcrConstants.VM_AGENT_FACTORY_PATH });
145 }
146
147 @Override
148 protected Object[] sort(Object parent, Object[] children) {
149 Object[] sorted = new Object[children.length];
150 System.arraycopy(children, 0, sorted, 0, children.length);
151 Arrays.sort(sorted, new ViewComparator());
152 return sorted;
153 }
154
155 @Override
156 protected List<Node> filterChildren(List<Node> children)
157 throws RepositoryException {
158 for (Iterator<Node> it = children.iterator(); it.hasNext();) {
159 Node node = it.next();
160 // execution spec definitions
161 if (node.getName().equals(SLC_EXECUTION_SPECS))
162 it.remove();
163 // flow values
164 else if (node.getParent().isNodeType(
165 SlcTypes.SLC_EXECUTION_FLOW))
166 it.remove();
167 }
168 return super.filterChildren(children);
169 }
170
171 @Override
172 public boolean hasChildren(Object element) {
173 if (element instanceof Node) {
174 Node node = (Node) element;
175 try {
176 if (node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW))
177 return false;
178 } catch (RepositoryException e) {
179 throw new SlcException("Cannot check has children", e);
180 }
181 }
182 return super.hasChildren(element);
183 }
184 }
185
186 static class ViewComparator implements Comparator<Object> {
187
188 public int compare(Object o1, Object o2) {
189 try {
190 if (o1 instanceof Node && o2 instanceof Node) {
191 Node node1 = (Node) o1;
192 Node node2 = (Node) o2;
193
194 if (node1.getName().equals(SLC_EXECUTION_SPECS))
195 return -100;
196 if (node2.getName().equals(SLC_EXECUTION_SPECS))
197 return 100;
198
199 if (node1.isNodeType(SLC_EXECUTION_FLOW)
200 && node2.isNodeType(SLC_EXECUTION_FLOW)) {
201 return node1.getName().compareTo(node2.getName());
202 } else if (node1.isNodeType(SLC_EXECUTION_FLOW)
203 && !node2.isNodeType(SLC_EXECUTION_FLOW)) {
204 return 1;
205 } else if (!node1.isNodeType(SLC_EXECUTION_FLOW)
206 && node2.isNodeType(SLC_EXECUTION_FLOW)) {
207 return -1;
208 } else {
209 // TODO: check title
210 return node1.getName().compareTo(node2.getName());
211 }
212 }
213 } catch (RepositoryException e) {
214 throw new ArgeoException("Cannot compare " + o1 + " and " + o2,
215 e);
216 }
217 return 0;
218 }
219
220 }
221
222 private void addContextMenu(TreeViewer flowsViewer) {
223
224 final MenuManager menuMgr = new MenuManager();
225 menuMgr.setRemoveAllWhenShown(true);
226 menuMgr.addMenuListener(new IMenuListener() {
227
228 public void menuAboutToShow(IMenuManager manager) {
229 menuMgr.add(new Action("Test") {
230 public void run() {
231 log.debug("do something");
232 }
233 });
234 }
235 });
236 Menu menu = menuMgr.createContextMenu(flowsViewer.getControl());
237 flowsViewer.getTree().setMenu(menu);
238 getSite().registerContextMenu(menuMgr, flowsViewer);
239 }
240
241 class VmAgentObserver extends AsyncUiEventListener {
242
243 public VmAgentObserver(Display display) {
244 super(display);
245 }
246
247 protected void onEventInUiThread(List<Event> events) {
248 for (Event event : events) {
249 try {
250 String path = event.getPath();
251
252 if (session.itemExists(path)) {
253 Node parentNode = session.getNode(path);// .getParent();
254 if (log.isTraceEnabled())
255 log.trace("Refresh " + parentNode + " after event "
256 + event);
257 viewer.refresh(parentNode);
258 }
259 } catch (RepositoryException e) {
260 log.warn("Cannot process event " + event + ": " + e);
261 }
262 }
263
264 // TODO: optimize based on event
265 viewer.refresh();
266 }
267 }
268
269 class ViewLabelProvider extends DefaultNodeLabelProvider implements
270 ITableLabelProvider {
271
272 @Override
273 protected String getText(Node node) throws RepositoryException {
274 if (node.isNodeType(NodeType.MIX_TITLE)
275 && node.hasProperty(Property.JCR_TITLE))
276 return node.getProperty(Property.JCR_TITLE).getString();
277 else if (node.getName().equals(SLC_EXECUTION_SPECS))
278 return "Execution Specifications";
279 else if (node.getPath().equals(
280 SlcJcrConstants.VM_AGENT_FACTORY_PATH))
281 return "Internal Agents";
282 return super.getText(node);
283 }
284
285 @Override
286 public Image getImage(Node node) throws RepositoryException {
287 // we try to optimize a bit by putting deeper nodes first
288 if (node.getParent().isNodeType(
289 SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
290 return SlcImages.CHOICES;
291 else if (node.isNodeType(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
292 return SlcImages.EXECUTION_SPEC_ATTRIBUTE;
293 else if (node.isNodeType(SlcTypes.SLC_EXECUTION_SPEC))
294 return SlcImages.EXECUTION_SPEC;
295 else if (node.getName().equals(SLC_EXECUTION_SPECS))
296 return SlcImages.EXECUTION_SPECS;
297 else if (node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW))
298 return SlcImages.FLOW;
299 else if (node.isNodeType(SlcTypes.SLC_MODULE)) {
300 if (node.getProperty(SLC_STARTED).getBoolean())
301 return SlcImages.MODULE;
302 else
303 return SlcImages.MODULE_STOPPED;
304 } else if (node.isNodeType(SlcTypes.SLC_AGENT))
305 return SlcImages.AGENT;
306 else if (node.isNodeType(SlcTypes.SLC_AGENT_FACTORY))
307 return SlcImages.AGENT_FACTORY;
308 else
309 return SlcImages.FOLDER;
310 }
311
312 public String getToolTipText(Node node) throws RepositoryException {
313 if (node.isNodeType(NodeType.MIX_TITLE)
314 && node.hasProperty(Property.JCR_DESCRIPTION))
315 return node.getProperty(Property.JCR_DESCRIPTION).getString();
316 return super.getToolTipText(node);
317 }
318
319 public String getColumnText(Object obj, int index) {
320 return getText(obj);
321 }
322
323 public Image getColumnImage(Object obj, int index) {
324 return getImage(obj);
325 }
326
327 }
328
329 class ViewDoubleClickListener implements IDoubleClickListener {
330 public void doubleClick(DoubleClickEvent evt) {
331 Object obj = ((IStructuredSelection) evt.getSelection())
332 .getFirstElement();
333 try {
334 if (obj instanceof Node) {
335 Node node = (Node) obj;
336 if (node.isNodeType(SLC_EXECUTION_MODULE)) {
337 ClientUiPlugin.startStopExecutionModule(modulesManager,
338 node);
339 } else {
340 String path = node.getPath();
341 // TODO factorize with editor
342 QueryManager qm = node.getSession().getWorkspace()
343 .getQueryManager();
344 String statement = "SELECT * FROM ["
345 + SlcTypes.SLC_EXECUTION_FLOW
346 + "] WHERE ISDESCENDANTNODE(['" + path
347 + "']) OR ISSAMENODE(['" + path + "'])";
348 // log.debug(statement);
349 Query query = qm.createQuery(statement, Query.JCR_SQL2);
350
351 // order paths
352 SortedSet<String> paths = new TreeSet<String>();
353 for (NodeIterator nit = query.execute().getNodes(); nit
354 .hasNext();) {
355 paths.add(nit.nextNode().getPath());
356 }
357
358 IWorkbenchPage activePage = PlatformUI.getWorkbench()
359 .getActiveWorkbenchWindow().getActivePage();
360 activePage.openEditor(new ProcessEditorInput(
361 new ArrayList<String>(paths), true),
362 ProcessEditor.ID);
363 }
364 }
365 } catch (Exception e) {
366 throw new SlcException("Cannot open " + obj, e);
367 }
368 }
369
370 }
371
372 /** Listen to drags */
373 class ViewDragListener extends DragSourceAdapter {
374
375 // Check if the drag action should start.
376 public void dragStart(DragSourceEvent event) {
377 // we only start drag if at least one of the selected elements is
378 // valid
379 boolean doIt = false;
380 IStructuredSelection selection = (IStructuredSelection) viewer
381 .getSelection();
382 @SuppressWarnings("rawtypes")
383 Iterator it = selection.iterator();
384 try {
385 while (it.hasNext()) {
386 Object obj = it.next();
387 if (obj instanceof Node) {
388 Node node = (Node) obj;
389 if (node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW)
390 || node.isNodeType(SlcTypes.SLC_EXECUTION_MODULE)) {
391 doIt = true;
392 }
393 }
394 }
395 } catch (RepositoryException e) {
396 throw new SlcException("Cannot read node to set drag data", e);
397 }
398 event.doit = doIt;
399 }
400
401 public void dragSetData(DragSourceEvent event) {
402 IStructuredSelection selection = (IStructuredSelection) viewer
403 .getSelection();
404 StringBuilder buf = new StringBuilder();
405 @SuppressWarnings("rawtypes")
406 Iterator it = selection.iterator();
407 try {
408
409 while (it.hasNext()) {
410 Object obj = it.next();
411
412 if (obj instanceof Node) {
413 Node node = (Node) obj;
414 if ((node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW) || node
415 .isNodeType(SlcTypes.SLC_EXECUTION_MODULE))
416 && TextTransfer.getInstance().isSupportedType(
417 event.dataType)) {
418 buf.append(node.getPath()).append('\n');
419 }
420 }
421 }
422 } catch (RepositoryException e) {
423 throw new SlcException("Cannot read node to set drag data", e);
424 }
425
426 if (buf.length() > 0) {
427 if (buf.charAt(buf.length() - 1) == '\n')
428 buf.deleteCharAt(buf.length() - 1);
429 event.data = buf.toString();
430 log.debug("data set to : " + buf.toString());
431 }
432 }
433 }
434
435 // DEPENDENCY INJECTION
436 public void setSession(Session session) {
437 this.session = session;
438 }
439
440 public void setModulesManager(ExecutionModulesManager modulesManager) {
441 this.modulesManager = modulesManager;
442 }
443 }