2 * Copyright (C) 2007-2012 Mathieu Baudier
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
.BasicNameVersion
;
45 import org
.argeo
.slc
.NameVersion
;
46 import org
.argeo
.slc
.SlcException
;
47 import org
.argeo
.slc
.client
.ui
.SlcImages
;
48 import org
.argeo
.slc
.client
.ui
.editors
.ProcessEditor
;
49 import org
.argeo
.slc
.client
.ui
.editors
.ProcessEditorInput
;
50 import org
.argeo
.slc
.execution
.ExecutionModulesManager
;
51 import org
.argeo
.slc
.jcr
.SlcJcrConstants
;
52 import org
.argeo
.slc
.jcr
.SlcNames
;
53 import org
.argeo
.slc
.jcr
.SlcTypes
;
54 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
55 import org
.eclipse
.core
.runtime
.IStatus
;
56 import org
.eclipse
.core
.runtime
.Status
;
57 import org
.eclipse
.core
.runtime
.jobs
.Job
;
58 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
59 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
60 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
61 import org
.eclipse
.jface
.viewers
.ITableLabelProvider
;
62 import org
.eclipse
.jface
.viewers
.TreeViewer
;
63 import org
.eclipse
.swt
.SWT
;
64 import org
.eclipse
.swt
.dnd
.DND
;
65 import org
.eclipse
.swt
.dnd
.DragSourceAdapter
;
66 import org
.eclipse
.swt
.dnd
.DragSourceEvent
;
67 import org
.eclipse
.swt
.dnd
.TextTransfer
;
68 import org
.eclipse
.swt
.dnd
.Transfer
;
69 import org
.eclipse
.swt
.graphics
.Image
;
70 import org
.eclipse
.swt
.widgets
.Composite
;
71 import org
.eclipse
.swt
.widgets
.Display
;
72 import org
.eclipse
.ui
.IWorkbenchPage
;
73 import org
.eclipse
.ui
.PlatformUI
;
74 import org
.eclipse
.ui
.part
.ViewPart
;
76 /** JCR based view of the execution modules. */
77 public class JcrExecutionModulesView
extends ViewPart
implements SlcTypes
,
79 private final static Log log
= LogFactory
80 .getLog(JcrExecutionModulesView
.class);
82 public static final String ID
= "org.argeo.slc.client.ui.jcrExecutionModulesView";
84 private TreeViewer viewer
;
86 private Session session
;
88 private ExecutionModulesManager modulesManager
;
90 public void createPartControl(Composite parent
) {
91 viewer
= new TreeViewer(parent
, SWT
.MULTI
| SWT
.H_SCROLL
| SWT
.V_SCROLL
);
92 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 getViewSite().setSelectionProvider(viewer
);
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());
109 String
[] nodeTypes
= { SlcTypes
.SLC_AGENT
,
110 SlcTypes
.SLC_AGENT_FACTORY
, SlcTypes
.SLC_EXECUTION_MODULE
};
111 session
.getWorkspace()
112 .getObservationManager()
114 new VmAgentObserver(viewer
.getTree().getDisplay()),
115 Event
.NODE_ADDED
| Event
.NODE_REMOVED
117 SlcJcrConstants
.VM_AGENT_FACTORY_PATH
, true, null,
119 } catch (RepositoryException e
) {
120 throw new SlcException("Cannot add observer", e
);
124 public void setFocus() {
125 viewer
.getControl().setFocus();
128 public TreeViewer
getViewer() {
132 public void refreshView() {
133 viewer
.setInput(getViewSite());
136 class ViewContentProvider
extends SimpleNodeContentProvider
{
138 public ViewContentProvider(Session session
) {
140 new String
[] { SlcJcrConstants
.VM_AGENT_FACTORY_PATH
});
144 // protected Object[] getChildren(Node node) throws RepositoryException
146 // if (node.isNodeType(SlcTypes.SLC_AGENT_FACTORY)) {
147 // List<AgentNodesWrapper> wrappers = new
148 // ArrayList<AgentNodesWrapper>();
149 // for (NodeIterator nit = node.getNodes(); nit.hasNext();) {
150 // wrappers.add(new AgentNodesWrapper(nit.nextNode()));
152 // return wrappers.toArray();
154 // return super.getChildren(node);
158 protected Object
[] sort(Object parent
, Object
[] children
) {
159 Object
[] sorted
= new Object
[children
.length
];
160 System
.arraycopy(children
, 0, sorted
, 0, children
.length
);
161 Arrays
.sort(sorted
, new ViewComparator());
166 protected List
<Node
> filterChildren(List
<Node
> children
)
167 throws RepositoryException
{
168 for (Iterator
<Node
> it
= children
.iterator(); it
.hasNext();) {
169 Node node
= it
.next();
170 // execution spec definitions
171 if (node
.getName().equals(SLC_EXECUTION_SPECS
))
174 else if (node
.getParent().isNodeType(
175 SlcTypes
.SLC_EXECUTION_FLOW
))
178 return super.filterChildren(children
);
182 public boolean hasChildren(Object element
) {
183 if (element
instanceof Node
) {
184 Node node
= (Node
) element
;
186 if (node
.isNodeType(SlcTypes
.SLC_EXECUTION_FLOW
))
188 } catch (RepositoryException e
) {
189 throw new SlcException("Cannot check has children", e
);
192 return super.hasChildren(element
);
196 static class ViewComparator
implements Comparator
<Object
> {
198 public int compare(Object o1
, Object o2
) {
200 if (o1
instanceof Node
&& o2
instanceof Node
) {
201 Node node1
= (Node
) o1
;
202 Node node2
= (Node
) o2
;
204 if (node1
.getName().equals(SLC_EXECUTION_SPECS
))
206 if (node2
.getName().equals(SLC_EXECUTION_SPECS
))
209 if (node1
.isNodeType(SLC_EXECUTION_FLOW
)
210 && node2
.isNodeType(SLC_EXECUTION_FLOW
)) {
211 return node1
.getName().compareTo(node2
.getName());
212 } else if (node1
.isNodeType(SLC_EXECUTION_FLOW
)
213 && !node2
.isNodeType(SLC_EXECUTION_FLOW
)) {
215 } else if (!node1
.isNodeType(SLC_EXECUTION_FLOW
)
216 && node2
.isNodeType(SLC_EXECUTION_FLOW
)) {
220 return node1
.getName().compareTo(node2
.getName());
223 } catch (RepositoryException e
) {
224 throw new ArgeoException("Cannot compare " + o1
+ " and " + o2
,
232 // /** Wraps the execution modules of an agent. */
233 // static class AgentNodesWrapper extends NodesWrapper {
235 // public AgentNodesWrapper(Node node) {
239 // protected List<WrappedNode> getWrappedNodes()
240 // throws RepositoryException {
241 // List<WrappedNode> children = new ArrayList<WrappedNode>();
242 // Node executionModules = getNode();
243 // for (NodeIterator nit = executionModules.getNodes(); nit.hasNext();) {
244 // for (NodeIterator nitVersions = nit.nextNode().getNodes(); nitVersions
246 // children.add(new WrappedNode(this, nitVersions.nextNode()));
254 class VmAgentObserver
extends AsyncUiEventListener
{
256 public VmAgentObserver(Display display
) {
260 protected void onEventInUiThread(List
<Event
> events
) {
261 for (Event event
: events
) {
263 String path
= event
.getPath();
265 if (session
.itemExists(path
)) {
266 Node parentNode
= session
.getNode(path
);// .getParent();
267 if (log
.isTraceEnabled())
268 log
.trace("Refresh " + parentNode
+ " after event "
270 viewer
.refresh(parentNode
);
272 } catch (RepositoryException e
) {
273 log
.warn("Cannot process event " + event
+ ": " + e
);
278 // Node vmAgentNode = session
279 // .getNode(SlcJcrConstants.VM_AGENT_FACTORY_PATH);
280 // viewer.refresh(vmAgentNode);
281 // } catch (RepositoryException e) {
282 // log.warn("Cannot process event : " + e);
284 // TODO: optimize based on event
289 class ViewLabelProvider
extends DefaultNodeLabelProvider
implements
290 ITableLabelProvider
{
293 protected String
getText(Node node
) throws RepositoryException
{
294 if (node
.isNodeType(NodeType
.MIX_TITLE
)
295 && node
.hasProperty(Property
.JCR_TITLE
))
296 return node
.getProperty(Property
.JCR_TITLE
).getString();
297 else if (node
.getName().equals(SLC_EXECUTION_SPECS
))
298 return "Execution Specifications";
299 else if (node
.getPath().equals(
300 SlcJcrConstants
.VM_AGENT_FACTORY_PATH
))
301 return "Internal Agents";
302 return super.getText(node
);
306 public Image
getImage(Node node
) throws RepositoryException
{
307 // we try to optimize a bit by putting deeper nodes first
308 if (node
.getParent().isNodeType(
309 SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
310 return SlcImages
.CHOICES
;
311 else if (node
.isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
312 return SlcImages
.EXECUTION_SPEC_ATTRIBUTE
;
313 else if (node
.isNodeType(SlcTypes
.SLC_EXECUTION_SPEC
))
314 return SlcImages
.EXECUTION_SPEC
;
315 else if (node
.getName().equals(SLC_EXECUTION_SPECS
))
316 return SlcImages
.EXECUTION_SPECS
;
317 else if (node
.isNodeType(SlcTypes
.SLC_EXECUTION_FLOW
))
318 return SlcImages
.FLOW
;
319 else if (node
.isNodeType(SlcTypes
.SLC_MODULE
)) {
320 if (node
.getProperty(SLC_STARTED
).getBoolean())
321 return SlcImages
.MODULE
;
323 return SlcImages
.MODULE_STOPPED
;
324 } else if (node
.isNodeType(SlcTypes
.SLC_AGENT
))
325 return SlcImages
.AGENT
;
326 else if (node
.isNodeType(SlcTypes
.SLC_AGENT_FACTORY
))
327 return SlcImages
.AGENT_FACTORY
;
329 return SlcImages
.FOLDER
;
332 public String
getToolTipText(Node node
) throws RepositoryException
{
333 if (node
.isNodeType(NodeType
.MIX_TITLE
)
334 && node
.hasProperty(Property
.JCR_DESCRIPTION
))
335 return node
.getProperty(Property
.JCR_DESCRIPTION
).getString();
336 return super.getToolTipText(node
);
339 public String
getColumnText(Object obj
, int index
) {
343 public Image
getColumnImage(Object obj
, int index
) {
344 return getImage(obj
);
349 class ViewDoubleClickListener
implements IDoubleClickListener
{
350 public void doubleClick(DoubleClickEvent evt
) {
351 Object obj
= ((IStructuredSelection
) evt
.getSelection())
354 if (obj
instanceof Node
) {
355 Node node
= (Node
) obj
;
356 if (node
.isNodeType(SLC_EXECUTION_MODULE
)) {
357 String name
= node
.getProperty(SLC_NAME
).getString();
358 String version
= node
.getProperty(SLC_VERSION
)
360 final NameVersion nameVersion
= new BasicNameVersion(
362 Boolean started
= node
.getProperty(SLC_STARTED
)
367 job
= new Job("Stop " + nameVersion
) {
368 protected IStatus
run(IProgressMonitor monitor
) {
369 monitor
.beginTask("Stop " + nameVersion
, 1);
370 modulesManager
.stop(nameVersion
);
372 return Status
.OK_STATUS
;
375 protected void canceling() {
376 getThread().interrupt();
381 job
= new Job("Start " + nameVersion
) {
382 protected IStatus
run(IProgressMonitor monitor
) {
383 monitor
.beginTask("Start " + nameVersion
, 1);
384 modulesManager
.start(nameVersion
);
386 return Status
.OK_STATUS
;
389 protected void canceling() {
390 getThread().interrupt();
398 String path
= node
.getPath();
399 // TODO factorize with editor
400 QueryManager qm
= node
.getSession().getWorkspace()
402 String statement
= "SELECT * FROM ["
403 + SlcTypes
.SLC_EXECUTION_FLOW
404 + "] WHERE ISDESCENDANTNODE(['" + path
405 + "']) OR ISSAMENODE(['" + path
+ "'])";
406 // log.debug(statement);
407 Query query
= qm
.createQuery(statement
, Query
.JCR_SQL2
);
410 SortedSet
<String
> paths
= new TreeSet
<String
>();
411 for (NodeIterator nit
= query
.execute().getNodes(); nit
413 paths
.add(nit
.nextNode().getPath());
416 // List<String> paths = new ArrayList<String>();
417 // paths.add(node.getPath());
418 IWorkbenchPage activePage
= PlatformUI
.getWorkbench()
419 .getActiveWorkbenchWindow().getActivePage();
420 activePage
.openEditor(new ProcessEditorInput(
421 new ArrayList
<String
>(paths
), true),
425 } catch (Exception e
) {
426 throw new SlcException("Cannot open " + obj
, e
);
432 class ViewDragListener
extends DragSourceAdapter
{
433 public void dragSetData(DragSourceEvent event
) {
434 IStructuredSelection selection
= (IStructuredSelection
) viewer
436 if (selection
.getFirstElement() instanceof Node
) {
437 Node node
= (Node
) selection
.getFirstElement();
439 // if (node.isNodeType(SLC_EXECUTION_FLOW)) {
440 // if (EditorInputTransfer.getInstance().isSupportedType(
441 // event.dataType)) {
442 // ProcessEditorInput pei = new ProcessEditorInput(
444 // EditorInputData eid = EditorInputTransfer
445 // .createEditorInputData(ProcessEditor.ID,
447 // event.data = new EditorInputTransfer.EditorInputData[] { eid
452 // } catch (RepositoryException e1) {
453 // throw new SlcException("Cannot drag " + node, e1);
456 if (TextTransfer
.getInstance().isSupportedType(event
.dataType
)) {
458 event
.data
= node
.getPath();
459 } catch (RepositoryException e1
) {
460 // TODO Auto-generated catch block
461 e1
.printStackTrace();
468 public void setSession(Session session
) {
469 this.session
= session
;
472 public void setModulesManager(ExecutionModulesManager modulesManager
) {
473 this.modulesManager
= modulesManager
;