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
.akb
.ui
.views
;
18 import java
.util
.ArrayList
;
19 import java
.util
.HashMap
;
20 import java
.util
.List
;
23 import javax
.jcr
.Node
;
24 import javax
.jcr
.NodeIterator
;
25 import javax
.jcr
.Repository
;
26 import javax
.jcr
.RepositoryException
;
27 import javax
.jcr
.Session
;
28 import javax
.jcr
.observation
.Event
;
29 import javax
.jcr
.observation
.EventListener
;
30 import javax
.jcr
.observation
.ObservationManager
;
32 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
33 import org
.argeo
.eclipse
.ui
.utils
.CommandUtils
;
34 import org
.argeo
.jcr
.JcrUtils
;
35 import org
.argeo
.slc
.akb
.AkbException
;
36 import org
.argeo
.slc
.akb
.AkbNames
;
37 import org
.argeo
.slc
.akb
.AkbService
;
38 import org
.argeo
.slc
.akb
.AkbTypes
;
39 import org
.argeo
.slc
.akb
.ui
.AkbUiPlugin
;
40 import org
.argeo
.slc
.akb
.ui
.AkbUiUtils
;
41 import org
.argeo
.slc
.akb
.ui
.commands
.DeleteAkbNodes
;
42 import org
.argeo
.slc
.akb
.ui
.commands
.OpenAkbNodeEditor
;
43 import org
.argeo
.slc
.akb
.ui
.providers
.AkbTreeLabelProvider
;
44 import org
.argeo
.slc
.akb
.ui
.providers
.TemplatesTreeContentProvider
;
45 import org
.argeo
.slc
.akb
.ui
.utils
.AkbItemsComparator
;
46 import org
.argeo
.slc
.akb
.ui
.utils
.Refreshable
;
47 import org
.argeo
.slc
.akb
.utils
.AkbJcrUtils
;
48 import org
.eclipse
.jface
.action
.IContributionItem
;
49 import org
.eclipse
.jface
.action
.IMenuListener
;
50 import org
.eclipse
.jface
.action
.IMenuManager
;
51 import org
.eclipse
.jface
.action
.MenuManager
;
52 import org
.eclipse
.jface
.viewers
.DoubleClickEvent
;
53 import org
.eclipse
.jface
.viewers
.IDoubleClickListener
;
54 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
55 import org
.eclipse
.jface
.viewers
.TreeViewer
;
56 import org
.eclipse
.swt
.SWT
;
57 import org
.eclipse
.swt
.layout
.GridData
;
58 import org
.eclipse
.swt
.widgets
.Composite
;
59 import org
.eclipse
.swt
.widgets
.Display
;
60 import org
.eclipse
.swt
.widgets
.Menu
;
61 import org
.eclipse
.ui
.IWorkbenchWindow
;
62 import org
.eclipse
.ui
.part
.ViewPart
;
63 import org
.eclipse
.ui
.services
.IServiceLocator
;
65 /** AKB template tree view. */
66 public class AkbTemplatesTreeView
extends ViewPart
implements Refreshable
{
67 // private final static Log log =
68 // LogFactory.getLog(AkbTemplatesTreeView.class);
70 public final static String ID
= AkbUiPlugin
.PLUGIN_ID
71 + ".akbTemplatesTreeView";
73 /* DEPENDENCY INJECTION */
74 private Session session
;
75 private AkbService akbService
;
78 private TreeViewer envTreeViewer
;
80 // Usefull business objects
81 private Node templatesParentNode
;
84 private EventListener akbNodesObserver
= null;
85 private final static String
[] observedNodeTypes
= {
86 AkbTypes
.AKB_ENV_TEMPLATE
, AkbTypes
.AKB_CONNECTOR_ALIAS
,
87 AkbTypes
.AKB_ITEM
, AkbTypes
.AKB_ITEM_FOLDER
,
88 AkbTypes
.AKB_CONNECTOR_FOLDER
};
90 private void initialize() {
92 templatesParentNode
= session
93 .getNode(AkbNames
.AKB_TEMPLATES_BASE_PATH
);
94 } catch (RepositoryException e
) {
95 throw new AkbException("unable to initialize AKB Browser view", e
);
100 public void createPartControl(Composite parent
) {
103 envTreeViewer
= createTreeViewer(parent
);
104 envTreeViewer
.setInput(initializeTree());
105 envTreeViewer
.setComparator(new AkbItemsComparator());
108 // The main tree viewer
109 protected TreeViewer
createTreeViewer(Composite parent
) {
110 parent
.setLayout(AkbUiUtils
.gridLayoutNoBorder());
111 int style
= SWT
.BORDER
| SWT
.MULTI
;
113 TreeViewer viewer
= new TreeViewer(parent
, style
);
114 viewer
.getTree().setLayoutData(
115 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
117 viewer
.setContentProvider(new TemplatesTreeContentProvider());
118 viewer
.setLabelProvider(new AkbTreeLabelProvider());
119 viewer
.addDoubleClickListener(new ViewDoubleClickListener());
121 // Add label provider with label decorator
122 // ResultTreeLabelProvider rtLblProvider = new
123 // ResultTreeLabelProvider();
124 // ILabelDecorator decorator = AkbUiPlugin.getDefault().getWorkbench()
125 // .getDecoratorManager().getLabelDecorator();
126 // viewer.setLabelProvider(new DecoratingLabelProvider(rtLblProvider,
129 getSite().setSelectionProvider(viewer
);
131 // // add drag & drop support
132 // int operations = DND.DROP_COPY | DND.DROP_MOVE;
133 // Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
134 // viewer.addDragSupport(operations, tt, new ViewDragListener());
135 // viewer.addDropSupport(operations, tt, new ViewDropListener(viewer));
138 MenuManager menuManager
= new MenuManager();
139 Menu menu
= menuManager
.createContextMenu(viewer
.getTree());
140 menuManager
.addMenuListener(new IMenuListener() {
141 public void menuAboutToShow(IMenuManager manager
) {
142 contextMenuAboutToShow(manager
);
145 viewer
.getTree().setMenu(menu
);
146 menuManager
.setRemoveAllWhenShown(true);
148 getSite().registerContextMenu(menuManager
, viewer
);
150 // Initialize observer
152 ObservationManager observationManager
= session
.getWorkspace()
153 .getObservationManager();
155 akbNodesObserver
= new AkbNodesObserver(viewer
.getTree()
157 observationManager
.addEventListener(akbNodesObserver
,
158 Event
.NODE_ADDED
| Event
.NODE_REMOVED
,
159 templatesParentNode
.getPath(), true, null,
160 observedNodeTypes
, false);
161 } catch (RepositoryException e
) {
162 throw new AkbException("Cannot register listeners", e
);
168 public void setFocus() {
171 private Node
[] initializeTree() {
173 NodeIterator ni
= templatesParentNode
.getNodes();
174 List
<Node
> templates
= new ArrayList
<Node
>();
175 while (ni
.hasNext()) {
176 Node currNode
= ni
.nextNode();
177 if (currNode
.isNodeType(AkbTypes
.AKB_ENV_TEMPLATE
))
178 templates
.add(currNode
);
180 Node
[] templateArr
= templates
.toArray(new Node
[templates
.size()]);
182 } catch (RepositoryException re
) {
183 throw new AkbException("Error while initializing templates Tree.",
189 public void forceRefresh(Object object
) {
190 envTreeViewer
.setInput(initializeTree());
193 // ///////////////////////////
194 // CONTEXT MENU MANAGEMENT
197 * Defines the commands that will pop up in the context menu.
199 protected void contextMenuAboutToShow(IMenuManager menuManager
) {
200 IWorkbenchWindow window
= AkbUiPlugin
.getDefault().getWorkbench()
201 .getActiveWorkbenchWindow();
205 IStructuredSelection selection
= (IStructuredSelection
) envTreeViewer
208 Node selected
= (Node
) selection
.getFirstElement();
211 boolean hasSelection
= selected
!= null;
214 currEnv
= AkbJcrUtils
.getCurrentTemplate(selected
);
216 boolean isTemplate
= hasSelection ? selected
217 .isNodeType(AkbTypes
.AKB_ENV_TEMPLATE
) : false;
218 boolean isParentItemsFolder
= hasSelection ? selected
219 .isNodeType(AkbTypes
.AKB_ITEM_FOLDER
) : false;
220 // boolean isParentConnectorsFolder = hasSelection ? selected
221 // .isNodeType(AkbTypes.AKB_CONNECTOR_FOLDER) : false;
222 boolean isDeletable
= hasSelection ?
true : false;
224 // Add Connector Alias
225 Map
<String
, String
> params
= new HashMap
<String
, String
>();
226 if (hasSelection
&& isTemplate
) {
227 params
.put(OpenAkbNodeEditor
.PARAM_PARENT_NODE_JCR_ID
,
228 selected
.getIdentifier());
229 params
.put(OpenAkbNodeEditor
.PARAM_CURR_ENV_JCR_ID
,
230 currEnv
.getIdentifier());
232 params
.put(OpenAkbNodeEditor
.PARAM_NODE_TYPE
,
233 AkbTypes
.AKB_CONNECTOR_ALIAS
);
235 // Connector Alias submenu
236 refreshAliasesSubmenu(menuManager
, window
, "menu.aliasesSubmenu",
237 "Add Connector Alias", isTemplate
, params
);
240 params
= new HashMap
<String
, String
>();
242 params
.put(OpenAkbNodeEditor
.PARAM_PARENT_NODE_JCR_ID
,
243 selected
.getIdentifier());
244 params
.put(OpenAkbNodeEditor
.PARAM_CURR_ENV_JCR_ID
,
245 currEnv
.getIdentifier());
247 refreshItemsSubmenu(menuManager
, window
, "menu.itemsSubmenu",
248 "Add Item", isParentItemsFolder
|| isTemplate
, params
);
251 params
= new HashMap
<String
, String
>();
253 params
.put(OpenAkbNodeEditor
.PARAM_PARENT_NODE_JCR_ID
,
254 selected
.getIdentifier());
255 params
.put(OpenAkbNodeEditor
.PARAM_CURR_ENV_JCR_ID
,
256 currEnv
.getIdentifier());
258 params
.put(OpenAkbNodeEditor
.PARAM_NODE_TYPE
,
259 AkbTypes
.AKB_ITEM_FOLDER
);
261 AkbUiUtils
.refreshParameterizedCommand(menuManager
, window
,
262 "cmd.addItemFolder", OpenAkbNodeEditor
.ID
,
263 "Add item folder", null, isParentItemsFolder
|| isTemplate
,
267 params
= new HashMap
<String
, String
>();
269 params
.put(DeleteAkbNodes
.PARAM_NODE_JCR_ID
,
270 selected
.getIdentifier());
271 AkbUiUtils
.refreshParameterizedCommand(menuManager
, window
,
272 "cmd.deleteItem", DeleteAkbNodes
.ID
,
273 "Delete selected item(s)", null, isDeletable
, params
);
276 params
= new HashMap
<String
, String
>();
277 params
.put(OpenAkbNodeEditor
.PARAM_PARENT_NODE_JCR_ID
,
278 templatesParentNode
.getIdentifier());
279 params
.put(OpenAkbNodeEditor
.PARAM_NODE_TYPE
,
280 AkbTypes
.AKB_ENV_TEMPLATE
);
281 AkbUiUtils
.refreshParameterizedCommand(menuManager
, window
,
282 "cmd.createTemplate", OpenAkbNodeEditor
.ID
,
283 "Create new template...", null,
284 !hasSelection
|| isTemplate
, params
);
286 } catch (RepositoryException re
) {
287 throw new AkbException("Error while refreshing context menu", re
);
293 * refreshes submenu with various connector types
302 private void refreshItemsSubmenu(IMenuManager menuManager
,
303 IServiceLocator locator
, String itemId
, String label
,
304 boolean isVisible
, Map
<String
, String
> params
) {
307 IContributionItem ici
= menuManager
.find(itemId
);
309 menuManager
.remove(ici
);
311 MenuManager subMenu
= new MenuManager(label
, itemId
);
314 Map
<String
, String
> tmpParams
= new HashMap
<String
, String
>();
315 tmpParams
.putAll(params
);
316 tmpParams
.put(OpenAkbNodeEditor
.PARAM_NODE_TYPE
,
317 AkbTypes
.AKB_JDBC_QUERY
);
318 String currItemId
= "cmd.createJDBCQuery";
319 IContributionItem currItem
= subMenu
.find(currItemId
);
320 if (currItem
!= null)
321 subMenu
.remove(currItem
);
322 subMenu
.add(AkbUiUtils
.createContributionItem(menuManager
, locator
,
323 currItemId
, OpenAkbNodeEditor
.ID
, "JDBC Query", null, tmpParams
));
326 tmpParams
= new HashMap
<String
, String
>();
327 tmpParams
.putAll(params
);
328 tmpParams
.put(OpenAkbNodeEditor
.PARAM_NODE_TYPE
,
329 AkbTypes
.AKB_SSH_COMMAND
);
330 currItemId
= "cmd.createSSHCommand";
331 currItem
= subMenu
.find(currItemId
);
332 if (currItem
!= null)
333 subMenu
.remove(currItem
);
334 subMenu
.add(AkbUiUtils
.createContributionItem(menuManager
, locator
,
335 currItemId
, OpenAkbNodeEditor
.ID
, "SSH Command", null,
339 tmpParams
= new HashMap
<String
, String
>();
340 tmpParams
.putAll(params
);
341 tmpParams
.put(OpenAkbNodeEditor
.PARAM_NODE_TYPE
, AkbTypes
.AKB_SSH_FILE
);
342 currItemId
= "cmd.createSSHFile";
343 currItem
= subMenu
.find(currItemId
);
344 if (currItem
!= null)
345 subMenu
.remove(currItem
);
346 subMenu
.add(AkbUiUtils
.createContributionItem(menuManager
, locator
,
347 currItemId
, OpenAkbNodeEditor
.ID
, "SSH File", null, tmpParams
));
350 menuManager
.add(subMenu
);
351 subMenu
.setVisible(isVisible
);
356 * refreshes submenu with various connector types
365 private void refreshAliasesSubmenu(IMenuManager menuManager
,
366 IServiceLocator locator
, String itemId
, String label
,
367 boolean isVisible
, Map
<String
, String
> params
) {
370 IContributionItem ici
= menuManager
.find(itemId
);
372 menuManager
.remove(ici
);
374 // TODO use dynamic contribution to dynamically retrieve specific
376 // CompoundContributionItem comConI = new MyCompoundCI(menuManager,
378 MenuManager subMenu
= new MenuManager(label
, itemId
);
381 Map
<String
, String
> tmpParams
= new HashMap
<String
, String
>();
382 tmpParams
.putAll(params
);
383 tmpParams
.put(OpenAkbNodeEditor
.PARAM_NODE_SUBTYPE
,
384 AkbTypes
.AKB_JDBC_CONNECTOR
);
385 String currItemId
= "cmd.createJDBCAlias";
386 IContributionItem currItem
= subMenu
.find(currItemId
);
387 if (currItem
!= null)
388 subMenu
.remove(currItem
);
389 subMenu
.add(AkbUiUtils
.createContributionItem(menuManager
, locator
,
390 currItemId
, OpenAkbNodeEditor
.ID
, "JDBC", null, tmpParams
));
393 tmpParams
= new HashMap
<String
, String
>();
394 tmpParams
.putAll(params
);
395 tmpParams
.put(OpenAkbNodeEditor
.PARAM_NODE_SUBTYPE
,
396 AkbTypes
.AKB_SSH_CONNECTOR
);
397 currItemId
= "cmd.createSSHAlias";
398 currItem
= subMenu
.find(currItemId
);
399 if (currItem
!= null)
400 subMenu
.remove(currItem
);
401 subMenu
.add(AkbUiUtils
.createContributionItem(menuManager
, locator
,
402 currItemId
, OpenAkbNodeEditor
.ID
, "SSH", null, tmpParams
));
405 menuManager
.add(subMenu
);
406 subMenu
.setVisible(isVisible
);
409 // private class MyCompoundCI extends CompoundContributionItem {
410 // private IMenuManager menuManager;
411 // private IServiceLocator locator;
413 // public MyCompoundCI(IMenuManager menuManager, IServiceLocator locator,
416 // this.menuManager = menuManager;
417 // this.locator = locator;
421 // protected IContributionItem[] getContributionItems() {
423 // CommandContributionItem[] submenu = new CommandContributionItem[2];
424 // submenu[0] = createContributionItem(menuManager, locator, "uid.1",
425 // OpenAkbNodeEditor.ID, "test1" + System.currentTimeMillis(),
427 // submenu[1] = createContributionItem(menuManager, locator, "uid.2",
428 // OpenAkbNodeEditor.ID, "test2", null, null);
434 private class AkbNodesObserver
extends AsyncUiEventListener
{
436 public AkbNodesObserver(Display display
) {
441 protected Boolean
willProcessInUiThread(List
<Event
> events
)
442 throws RepositoryException
{
443 // unfiltered for the time being
447 protected void onEventInUiThread(List
<Event
> events
)
448 throws RepositoryException
{
449 boolean fullRefresh
= false;
451 eventLoop
: for (Event event
: events
) {
452 String currPath
= event
.getPath();
453 if (session
.nodeExists(currPath
)) {
454 Node node
= session
.getNode(currPath
);
455 if (node
.isNodeType(AkbTypes
.AKB_ENV_TEMPLATE
)) {
462 Object
[] visibles
= envTreeViewer
.getExpandedElements();
464 envTreeViewer
.setInput(initializeTree());
466 envTreeViewer
.refresh();
468 envTreeViewer
.setExpandedElements(visibles
);
472 class ViewDoubleClickListener
implements IDoubleClickListener
{
473 public void doubleClick(DoubleClickEvent evt
) {
474 Object obj
= ((IStructuredSelection
) evt
.getSelection())
477 if (obj
instanceof Node
) {
478 Node node
= (Node
) obj
;
479 Node currEnv
= AkbJcrUtils
.getCurrentTemplate(node
);
481 // Add Connector Alias
482 Map
<String
, String
> params
= new HashMap
<String
, String
>();
483 params
.put(OpenAkbNodeEditor
.PARAM_NODE_JCR_ID
,
484 node
.getIdentifier());
485 params
.put(OpenAkbNodeEditor
.PARAM_CURR_ENV_JCR_ID
,
486 currEnv
.getIdentifier());
488 CommandUtils
.callCommand(OpenAkbNodeEditor
.ID
, params
);
490 } catch (RepositoryException e
) {
491 throw new AkbException("Cannot open " + obj
, e
);
497 public void dispose() {
498 JcrUtils
.logoutQuietly(session
);
502 /* DEPENDENCY INJECTION */
503 public void setRepository(Repository repository
) {
505 session
= repository
.login();
506 } catch (RepositoryException e
) {
507 throw new AkbException("unable to log in for " + ID
+ " view");
511 public void setAkbService(AkbService akbService
) {
512 this.akbService
= akbService
;