]> git.argeo.org Git - gpl/argeo-slc.git/blob - plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/views/AkbTemplatesTreeView.java
2686a486de780adb3f154431be3c69fc68230ed6
[gpl/argeo-slc.git] / plugins / org.argeo.slc.akb.ui / src / main / java / org / argeo / slc / akb / ui / views / AkbTemplatesTreeView.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.akb.ui.views;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
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;
31
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;
64
65 /** AKB template tree view. */
66 public class AkbTemplatesTreeView extends ViewPart implements Refreshable {
67 // private final static Log log =
68 // LogFactory.getLog(AkbTemplatesTreeView.class);
69
70 public final static String ID = AkbUiPlugin.PLUGIN_ID
71 + ".akbTemplatesTreeView";
72
73 /* DEPENDENCY INJECTION */
74 private Session session;
75 private AkbService akbService;
76
77 // This page widgets
78 private TreeViewer envTreeViewer;
79
80 // Usefull business objects
81 private Node templatesParentNode;
82
83 // Observer
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 };
89
90 private void initialize() {
91 try {
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);
96 }
97 }
98
99 @Override
100 public void createPartControl(Composite parent) {
101 initialize();
102
103 envTreeViewer = createTreeViewer(parent);
104 envTreeViewer.setInput(initializeTree());
105 envTreeViewer.setComparator(new AkbItemsComparator());
106 }
107
108 // The main tree viewer
109 protected TreeViewer createTreeViewer(Composite parent) {
110 parent.setLayout(AkbUiUtils.gridLayoutNoBorder());
111 int style = SWT.BORDER | SWT.MULTI;
112
113 TreeViewer viewer = new TreeViewer(parent, style);
114 viewer.getTree().setLayoutData(
115 new GridData(SWT.FILL, SWT.FILL, true, true));
116
117 viewer.setContentProvider(new TemplatesTreeContentProvider());
118 viewer.setLabelProvider(new AkbTreeLabelProvider());
119 viewer.addDoubleClickListener(new ViewDoubleClickListener());
120
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,
127 // decorator));
128
129 getSite().setSelectionProvider(viewer);
130
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));
136
137 // add context menu
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);
143 }
144 });
145 viewer.getTree().setMenu(menu);
146 menuManager.setRemoveAllWhenShown(true);
147
148 getSite().registerContextMenu(menuManager, viewer);
149
150 // Initialize observer
151 try {
152 ObservationManager observationManager = session.getWorkspace()
153 .getObservationManager();
154
155 akbNodesObserver = new AkbNodesObserver(viewer.getTree()
156 .getDisplay());
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);
163 }
164 return viewer;
165 }
166
167 @Override
168 public void setFocus() {
169 }
170
171 private Node[] initializeTree() {
172 try {
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);
179 }
180 Node[] templateArr = templates.toArray(new Node[templates.size()]);
181 return templateArr;
182 } catch (RepositoryException re) {
183 throw new AkbException("Error while initializing templates Tree.",
184 re);
185 }
186 }
187
188 @Override
189 public void forceRefresh(Object object) {
190 envTreeViewer.setInput(initializeTree());
191 }
192
193 // ///////////////////////////
194 // CONTEXT MENU MANAGEMENT
195
196 /**
197 * Defines the commands that will pop up in the context menu.
198 **/
199 protected void contextMenuAboutToShow(IMenuManager menuManager) {
200 IWorkbenchWindow window = AkbUiPlugin.getDefault().getWorkbench()
201 .getActiveWorkbenchWindow();
202 try {
203
204 // Build conditions
205 IStructuredSelection selection = (IStructuredSelection) envTreeViewer
206 .getSelection();
207
208 Node selected = (Node) selection.getFirstElement();
209 Node currEnv = null;
210
211 boolean hasSelection = selected != null;
212
213 if (hasSelection)
214 currEnv = AkbJcrUtils.getCurrentTemplate(selected);
215
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;
223
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());
231 }
232 params.put(OpenAkbNodeEditor.PARAM_NODE_TYPE,
233 AkbTypes.AKB_CONNECTOR_ALIAS);
234
235 // Connector Alias submenu
236 refreshAliasesSubmenu(menuManager, window, "menu.aliasesSubmenu",
237 "Add Connector Alias", isTemplate, params);
238
239 // Item Submenu
240 params = new HashMap<String, String>();
241 if (hasSelection) {
242 params.put(OpenAkbNodeEditor.PARAM_PARENT_NODE_JCR_ID,
243 selected.getIdentifier());
244 params.put(OpenAkbNodeEditor.PARAM_CURR_ENV_JCR_ID,
245 currEnv.getIdentifier());
246 }
247 refreshItemsSubmenu(menuManager, window, "menu.itemsSubmenu",
248 "Add Item", isParentItemsFolder || isTemplate, params);
249
250 // Add Item Folder
251 params = new HashMap<String, String>();
252 if (hasSelection) {
253 params.put(OpenAkbNodeEditor.PARAM_PARENT_NODE_JCR_ID,
254 selected.getIdentifier());
255 params.put(OpenAkbNodeEditor.PARAM_CURR_ENV_JCR_ID,
256 currEnv.getIdentifier());
257 }
258 params.put(OpenAkbNodeEditor.PARAM_NODE_TYPE,
259 AkbTypes.AKB_ITEM_FOLDER);
260
261 AkbUiUtils.refreshParameterizedCommand(menuManager, window,
262 "cmd.addItemFolder", OpenAkbNodeEditor.ID,
263 "Add item folder", null, isParentItemsFolder || isTemplate,
264 params);
265
266 // Delete Item
267 params = new HashMap<String, String>();
268 if (hasSelection)
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);
274
275 // create template
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);
285
286 } catch (RepositoryException re) {
287 throw new AkbException("Error while refreshing context menu", re);
288 }
289 }
290
291 /**
292 *
293 * refreshes submenu with various connector types
294 *
295 * @param menuManager
296 * @param locator
297 * @param itemId
298 * @param label
299 * @param isVisible
300 * @param params
301 */
302 private void refreshItemsSubmenu(IMenuManager menuManager,
303 IServiceLocator locator, String itemId, String label,
304 boolean isVisible, Map<String, String> params) {
305
306 // clean
307 IContributionItem ici = menuManager.find(itemId);
308 if (ici != null)
309 menuManager.remove(ici);
310
311 MenuManager subMenu = new MenuManager(label, itemId);
312
313 // JDBC Query
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));
324
325 // SSH COMMAND
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,
336 tmpParams));
337
338 // SSH FILE
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));
348
349 // refresh
350 menuManager.add(subMenu);
351 subMenu.setVisible(isVisible);
352 }
353
354 /**
355 *
356 * refreshes submenu with various connector types
357 *
358 * @param menuManager
359 * @param locator
360 * @param itemId
361 * @param label
362 * @param isVisible
363 * @param params
364 */
365 private void refreshAliasesSubmenu(IMenuManager menuManager,
366 IServiceLocator locator, String itemId, String label,
367 boolean isVisible, Map<String, String> params) {
368
369 // clean
370 IContributionItem ici = menuManager.find(itemId);
371 if (ici != null)
372 menuManager.remove(ici);
373
374 // TODO use dynamic contribution to dynamically retrieve specific
375 // connector types
376 // CompoundContributionItem comConI = new MyCompoundCI(menuManager,
377 // locator, itemId);
378 MenuManager subMenu = new MenuManager(label, itemId);
379
380 // JDBC
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));
391
392 // SSH
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));
403
404 // refresh
405 menuManager.add(subMenu);
406 subMenu.setVisible(isVisible);
407 }
408
409 // private class MyCompoundCI extends CompoundContributionItem {
410 // private IMenuManager menuManager;
411 // private IServiceLocator locator;
412 //
413 // public MyCompoundCI(IMenuManager menuManager, IServiceLocator locator,
414 // String itemId) {
415 // super(itemId);
416 // this.menuManager = menuManager;
417 // this.locator = locator;
418 // }
419 //
420 // @Override
421 // protected IContributionItem[] getContributionItems() {
422 //
423 // CommandContributionItem[] submenu = new CommandContributionItem[2];
424 // submenu[0] = createContributionItem(menuManager, locator, "uid.1",
425 // OpenAkbNodeEditor.ID, "test1" + System.currentTimeMillis(),
426 // null, null);
427 // submenu[1] = createContributionItem(menuManager, locator, "uid.2",
428 // OpenAkbNodeEditor.ID, "test2", null, null);
429 // return submenu;
430 // }
431 // }
432
433 /* INNER CLASSES */
434 private class AkbNodesObserver extends AsyncUiEventListener {
435
436 public AkbNodesObserver(Display display) {
437 super(display);
438 }
439
440 @Override
441 protected Boolean willProcessInUiThread(List<Event> events)
442 throws RepositoryException {
443 // unfiltered for the time being
444 return true;
445 }
446
447 protected void onEventInUiThread(List<Event> events)
448 throws RepositoryException {
449 boolean fullRefresh = false;
450
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)) {
456 fullRefresh = true;
457 break eventLoop;
458 }
459 }
460 }
461
462 Object[] visibles = envTreeViewer.getExpandedElements();
463 if (fullRefresh)
464 envTreeViewer.setInput(initializeTree());
465 else
466 envTreeViewer.refresh();
467
468 envTreeViewer.setExpandedElements(visibles);
469 }
470 }
471
472 class ViewDoubleClickListener implements IDoubleClickListener {
473 public void doubleClick(DoubleClickEvent evt) {
474 Object obj = ((IStructuredSelection) evt.getSelection())
475 .getFirstElement();
476 try {
477 if (obj instanceof Node) {
478 Node node = (Node) obj;
479 Node currEnv = AkbJcrUtils.getCurrentTemplate(node);
480
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());
487
488 CommandUtils.callCommand(OpenAkbNodeEditor.ID, params);
489 }
490 } catch (RepositoryException e) {
491 throw new AkbException("Cannot open " + obj, e);
492 }
493 }
494 }
495
496 @Override
497 public void dispose() {
498 JcrUtils.logoutQuietly(session);
499 super.dispose();
500 }
501
502 /* DEPENDENCY INJECTION */
503 public void setRepository(Repository repository) {
504 try {
505 session = repository.login();
506 } catch (RepositoryException e) {
507 throw new AkbException("unable to log in for " + ID + " view");
508 }
509 }
510
511 public void setAkbService(AkbService akbService) {
512 this.akbService = akbService;
513
514 }
515 }