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