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