2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.slc
.client
.ui
.views
;
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
;
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
;
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
;
71 /** JCR based view of the execution modules. */
72 public class JcrExecutionModulesView
extends ViewPart
implements SlcTypes
,
74 private final static Log log
= LogFactory
75 .getLog(JcrExecutionModulesView
.class);
77 public static final String ID
= ClientUiPlugin
.ID
78 + ".jcrExecutionModulesView";
80 private TreeViewer viewer
;
82 /* DEPENDENCY INJECTION */
83 private Session session
;
84 private ExecutionModulesManager modulesManager
;
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());
97 // addContextMenu(viewer);
99 getViewSite().setSelectionProvider(viewer
);
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());
107 String
[] nodeTypes
= { SlcTypes
.SLC_AGENT
,
108 SlcTypes
.SLC_AGENT_FACTORY
, SlcTypes
.SLC_EXECUTION_MODULE
};
109 session
.getWorkspace()
110 .getObservationManager()
112 new VmAgentObserver(viewer
.getTree().getDisplay()),
113 Event
.NODE_ADDED
| Event
.NODE_REMOVED
115 SlcJcrConstants
.VM_AGENT_FACTORY_PATH
, true, null,
117 } catch (RepositoryException e
) {
118 throw new SlcException("Cannot add observer", e
);
122 public void setFocus() {
123 viewer
.getControl().setFocus();
126 public TreeViewer
getViewer() {
130 public void refreshView() {
131 viewer
.setInput(getViewSite());
135 class ViewContentProvider
extends SimpleNodeContentProvider
{
137 public ViewContentProvider(Session session
) {
139 new String
[] { SlcJcrConstants
.VM_AGENT_FACTORY_PATH
});
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());
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
))
159 else if (node
.getParent().isNodeType(
160 SlcTypes
.SLC_EXECUTION_FLOW
))
163 return super.filterChildren(children
);
167 public boolean hasChildren(Object element
) {
168 if (element
instanceof Node
) {
169 Node node
= (Node
) element
;
171 if (node
.isNodeType(SlcTypes
.SLC_EXECUTION_FLOW
))
173 } catch (RepositoryException e
) {
174 throw new SlcException("Cannot check has children", e
);
177 return super.hasChildren(element
);
181 static class ViewComparator
implements Comparator
<Object
> {
183 public int compare(Object o1
, Object o2
) {
185 if (o1
instanceof Node
&& o2
instanceof Node
) {
186 Node node1
= (Node
) o1
;
187 Node node2
= (Node
) o2
;
189 if (node1
.getName().equals(SLC_EXECUTION_SPECS
))
191 if (node2
.getName().equals(SLC_EXECUTION_SPECS
))
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
)) {
200 } else if (!node1
.isNodeType(SLC_EXECUTION_FLOW
)
201 && node2
.isNodeType(SLC_EXECUTION_FLOW
)) {
205 return node1
.getName().compareTo(node2
.getName());
208 } catch (RepositoryException e
) {
209 throw new ArgeoException("Cannot compare " + o1
+ " and " + o2
,
217 // private void addContextMenu(TreeViewer flowsViewer) {
219 // final MenuManager menuMgr = new MenuManager();
220 // menuMgr.setRemoveAllWhenShown(true);
221 // menuMgr.addMenuListener(new IMenuListener() {
223 // public void menuAboutToShow(IMenuManager manager) {
224 // menuMgr.add(new Action("Test") {
225 // public void run() {
226 // log.debug("do something");
231 // Menu menu = menuMgr.createContextMenu(flowsViewer.getControl());
232 // flowsViewer.getTree().setMenu(menu);
233 // getSite().registerContextMenu(menuMgr, flowsViewer);
236 class VmAgentObserver
extends AsyncUiEventListener
{
238 public VmAgentObserver(Display display
) {
242 protected void onEventInUiThread(List
<Event
> events
) {
243 for (Event event
: events
) {
245 String path
= event
.getPath();
247 if (session
.itemExists(path
)) {
248 Node parentNode
= session
.getNode(path
);// .getParent();
249 if (log
.isTraceEnabled())
250 log
.trace("Refresh " + parentNode
+ " after event "
252 viewer
.refresh(parentNode
);
254 } catch (RepositoryException e
) {
255 log
.warn("Cannot process event " + event
+ ": " + e
);
259 // TODO: optimize based on event
264 class ViewLabelProvider
extends DefaultNodeLabelProvider
implements
265 ITableLabelProvider
{
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
);
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
;
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
;
304 return SlcImages
.FOLDER
;
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
);
314 public String
getColumnText(Object obj
, int index
) {
318 public Image
getColumnImage(Object obj
, int index
) {
319 return getImage(obj
);
324 class ViewDoubleClickListener
implements IDoubleClickListener
{
325 public void doubleClick(DoubleClickEvent evt
) {
326 Object obj
= ((IStructuredSelection
) evt
.getSelection())
329 if (obj
instanceof Node
) {
330 Node node
= (Node
) obj
;
331 if (node
.isNodeType(SLC_EXECUTION_MODULE
)) {
332 ClientUiPlugin
.startStopExecutionModule(modulesManager
,
335 String path
= node
.getPath();
336 // TODO factorize with editor
337 QueryManager qm
= node
.getSession().getWorkspace()
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
);
347 SortedSet
<String
> paths
= new TreeSet
<String
>();
348 for (NodeIterator nit
= query
.execute().getNodes(); nit
350 paths
.add(nit
.nextNode().getPath());
353 IWorkbenchPage activePage
= PlatformUI
.getWorkbench()
354 .getActiveWorkbenchWindow().getActivePage();
355 activePage
.openEditor(new ProcessEditorInput(
356 new ArrayList
<String
>(paths
), true),
360 } catch (Exception e
) {
361 throw new SlcException("Cannot open " + obj
, e
);
367 /** Listen to drags */
368 class ViewDragListener
extends DragSourceAdapter
{
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
374 boolean doIt
= false;
375 IStructuredSelection selection
= (IStructuredSelection
) viewer
377 @SuppressWarnings("rawtypes")
378 Iterator it
= selection
.iterator();
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
)) {
390 } catch (RepositoryException e
) {
391 throw new SlcException("Cannot read node to set drag data", e
);
396 public void dragSetData(DragSourceEvent event
) {
397 IStructuredSelection selection
= (IStructuredSelection
) viewer
399 StringBuilder buf
= new StringBuilder();
400 @SuppressWarnings("rawtypes")
401 Iterator it
= selection
.iterator();
404 while (it
.hasNext()) {
405 Object obj
= it
.next();
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(
413 buf
.append(node
.getPath()).append('\n');
417 } catch (RepositoryException e
) {
418 throw new SlcException("Cannot read node to set drag data", e
);
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());
430 // DEPENDENCY INJECTION
431 public void setSession(Session session
) {
432 this.session
= session
;
435 public void setModulesManager(ExecutionModulesManager modulesManager
) {
436 this.modulesManager
= modulesManager
;