]> 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
fix a bug on tree observer
[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 = "org.argeo.slc.client.ui.jcrExecutionModulesView";
78
79 private TreeViewer viewer;
80
81 private Session session;
82
83 private ExecutionModulesManager modulesManager;
84
85 public void createPartControl(Composite parent) {
86 viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
87 EclipseUiSpecificUtils.enableToolTipSupport(viewer);
88
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 getViewSite().setSelectionProvider(viewer);
97
98 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
99 // Transfer[] tt = new Transfer[] { EditorInputTransfer.getInstance() };
100 int operations = DND.DROP_COPY | DND.DROP_MOVE;
101 viewer.addDragSupport(operations, tt, new ViewDragListener());
102
103 try {
104 String[] nodeTypes = { SlcTypes.SLC_AGENT,
105 SlcTypes.SLC_AGENT_FACTORY, SlcTypes.SLC_EXECUTION_MODULE };
106 session.getWorkspace()
107 .getObservationManager()
108 .addEventListener(
109 new VmAgentObserver(viewer.getTree().getDisplay()),
110 Event.NODE_ADDED | Event.NODE_REMOVED
111 | Event.NODE_MOVED,
112 SlcJcrConstants.VM_AGENT_FACTORY_PATH, true, null,
113 nodeTypes, false);
114 } catch (RepositoryException e) {
115 throw new SlcException("Cannot add observer", e);
116 }
117 }
118
119 public void setFocus() {
120 viewer.getControl().setFocus();
121 }
122
123 public TreeViewer getViewer() {
124 return viewer;
125 }
126
127 public void refreshView() {
128 viewer.setInput(getViewSite());
129 }
130
131 class ViewContentProvider extends SimpleNodeContentProvider {
132
133 public ViewContentProvider(Session session) {
134 super(session,
135 new String[] { SlcJcrConstants.VM_AGENT_FACTORY_PATH });
136 }
137
138 @Override
139 protected Object[] sort(Object parent, Object[] children) {
140 Object[] sorted = new Object[children.length];
141 System.arraycopy(children, 0, sorted, 0, children.length);
142 Arrays.sort(sorted, new ViewComparator());
143 return sorted;
144 }
145
146 @Override
147 protected List<Node> filterChildren(List<Node> children)
148 throws RepositoryException {
149 for (Iterator<Node> it = children.iterator(); it.hasNext();) {
150 Node node = it.next();
151 // execution spec definitions
152 if (node.getName().equals(SLC_EXECUTION_SPECS))
153 it.remove();
154 // flow values
155 else if (node.getParent().isNodeType(
156 SlcTypes.SLC_EXECUTION_FLOW))
157 it.remove();
158 }
159 return super.filterChildren(children);
160 }
161
162 @Override
163 public boolean hasChildren(Object element) {
164 if (element instanceof Node) {
165 Node node = (Node) element;
166 try {
167 if (node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW))
168 return false;
169 } catch (RepositoryException e) {
170 throw new SlcException("Cannot check has children", e);
171 }
172 }
173 return super.hasChildren(element);
174 }
175 }
176
177 static class ViewComparator implements Comparator<Object> {
178
179 public int compare(Object o1, Object o2) {
180 try {
181 if (o1 instanceof Node && o2 instanceof Node) {
182 Node node1 = (Node) o1;
183 Node node2 = (Node) o2;
184
185 if (node1.getName().equals(SLC_EXECUTION_SPECS))
186 return -100;
187 if (node2.getName().equals(SLC_EXECUTION_SPECS))
188 return 100;
189
190 if (node1.isNodeType(SLC_EXECUTION_FLOW)
191 && node2.isNodeType(SLC_EXECUTION_FLOW)) {
192 return node1.getName().compareTo(node2.getName());
193 } else if (node1.isNodeType(SLC_EXECUTION_FLOW)
194 && !node2.isNodeType(SLC_EXECUTION_FLOW)) {
195 return 1;
196 } else if (!node1.isNodeType(SLC_EXECUTION_FLOW)
197 && node2.isNodeType(SLC_EXECUTION_FLOW)) {
198 return -1;
199 } else {
200 // TODO: check title
201 return node1.getName().compareTo(node2.getName());
202 }
203 }
204 } catch (RepositoryException e) {
205 throw new ArgeoException("Cannot compare " + o1 + " and " + o2,
206 e);
207 }
208 return 0;
209 }
210
211 }
212
213 class VmAgentObserver extends AsyncUiEventListener {
214
215 public VmAgentObserver(Display display) {
216 super(display);
217 }
218
219 protected void onEventInUiThread(List<Event> events) {
220 for (Event event : events) {
221 try {
222 String path = event.getPath();
223
224 if (session.itemExists(path)) {
225 Node parentNode = session.getNode(path);// .getParent();
226 if (log.isTraceEnabled())
227 log.trace("Refresh " + parentNode + " after event "
228 + event);
229 viewer.refresh(parentNode);
230 }
231 } catch (RepositoryException e) {
232 log.warn("Cannot process event " + event + ": " + e);
233 }
234 }
235
236 // TODO: optimize based on event
237 viewer.refresh();
238 }
239 }
240
241 class ViewLabelProvider extends DefaultNodeLabelProvider implements
242 ITableLabelProvider {
243
244 @Override
245 protected String getText(Node node) throws RepositoryException {
246 if (node.isNodeType(NodeType.MIX_TITLE)
247 && node.hasProperty(Property.JCR_TITLE))
248 return node.getProperty(Property.JCR_TITLE).getString();
249 else if (node.getName().equals(SLC_EXECUTION_SPECS))
250 return "Execution Specifications";
251 else if (node.getPath().equals(
252 SlcJcrConstants.VM_AGENT_FACTORY_PATH))
253 return "Internal Agents";
254 return super.getText(node);
255 }
256
257 @Override
258 public Image getImage(Node node) throws RepositoryException {
259 // we try to optimize a bit by putting deeper nodes first
260 if (node.getParent().isNodeType(
261 SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
262 return SlcImages.CHOICES;
263 else if (node.isNodeType(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
264 return SlcImages.EXECUTION_SPEC_ATTRIBUTE;
265 else if (node.isNodeType(SlcTypes.SLC_EXECUTION_SPEC))
266 return SlcImages.EXECUTION_SPEC;
267 else if (node.getName().equals(SLC_EXECUTION_SPECS))
268 return SlcImages.EXECUTION_SPECS;
269 else if (node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW))
270 return SlcImages.FLOW;
271 else if (node.isNodeType(SlcTypes.SLC_MODULE)) {
272 if (node.getProperty(SLC_STARTED).getBoolean())
273 return SlcImages.MODULE;
274 else
275 return SlcImages.MODULE_STOPPED;
276 } else if (node.isNodeType(SlcTypes.SLC_AGENT))
277 return SlcImages.AGENT;
278 else if (node.isNodeType(SlcTypes.SLC_AGENT_FACTORY))
279 return SlcImages.AGENT_FACTORY;
280 else
281 return SlcImages.FOLDER;
282 }
283
284 public String getToolTipText(Node node) throws RepositoryException {
285 if (node.isNodeType(NodeType.MIX_TITLE)
286 && node.hasProperty(Property.JCR_DESCRIPTION))
287 return node.getProperty(Property.JCR_DESCRIPTION).getString();
288 return super.getToolTipText(node);
289 }
290
291 public String getColumnText(Object obj, int index) {
292 return getText(obj);
293 }
294
295 public Image getColumnImage(Object obj, int index) {
296 return getImage(obj);
297 }
298
299 }
300
301 class ViewDoubleClickListener implements IDoubleClickListener {
302 public void doubleClick(DoubleClickEvent evt) {
303 Object obj = ((IStructuredSelection) evt.getSelection())
304 .getFirstElement();
305 try {
306 if (obj instanceof Node) {
307 Node node = (Node) obj;
308 if (node.isNodeType(SLC_EXECUTION_MODULE)) {
309 ClientUiPlugin.startStopExecutionModule(modulesManager,
310 node);
311 } else {
312 String path = node.getPath();
313 // TODO factorize with editor
314 QueryManager qm = node.getSession().getWorkspace()
315 .getQueryManager();
316 String statement = "SELECT * FROM ["
317 + SlcTypes.SLC_EXECUTION_FLOW
318 + "] WHERE ISDESCENDANTNODE(['" + path
319 + "']) OR ISSAMENODE(['" + path + "'])";
320 // log.debug(statement);
321 Query query = qm.createQuery(statement, Query.JCR_SQL2);
322
323 // order paths
324 SortedSet<String> paths = new TreeSet<String>();
325 for (NodeIterator nit = query.execute().getNodes(); nit
326 .hasNext();) {
327 paths.add(nit.nextNode().getPath());
328 }
329
330 IWorkbenchPage activePage = PlatformUI.getWorkbench()
331 .getActiveWorkbenchWindow().getActivePage();
332 activePage.openEditor(new ProcessEditorInput(
333 new ArrayList<String>(paths), true),
334 ProcessEditor.ID);
335 }
336 }
337 } catch (Exception e) {
338 throw new SlcException("Cannot open " + obj, e);
339 }
340 }
341
342 }
343
344 /** Listen to drags */
345 class ViewDragListener extends DragSourceAdapter {
346 public void dragSetData(DragSourceEvent event) {
347 IStructuredSelection selection = (IStructuredSelection) viewer
348 .getSelection();
349 if (selection.getFirstElement() instanceof Node) {
350 Node node = (Node) selection.getFirstElement();
351 if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
352 try {
353 event.data = node.getPath();
354 } catch (RepositoryException e) {
355 throw new SlcException("Cannot read node", e);
356 }
357 }
358 }
359 }
360 }
361
362 public void setSession(Session session) {
363 this.session = session;
364 }
365
366 public void setModulesManager(ExecutionModulesManager modulesManager) {
367 this.modulesManager = modulesManager;
368 }
369
370 }