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