]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/DistributionsView.java
Work on the modular distribution - generate binaries, work on layout.
[gpl/argeo-slc.git] / plugins / org.argeo.slc.client.ui.dist / src / main / java / org / argeo / slc / client / ui / dist / views / DistributionsView.java
index 26e38f1bbbebfdbefd0cc38a4fd945bc809e294f..2838863173137385986c2816d043bc8193b2fecc 100644 (file)
  */
 package org.argeo.slc.client.ui.dist.views;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
-import javax.jcr.Credentials;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.query.Query;
-import javax.jcr.query.QueryResult;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoMonitor;
-import org.argeo.eclipse.ui.EclipseArgeoMonitor;
-import org.argeo.eclipse.ui.ErrorFeedback;
+
 import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ArgeoJcrUtils;
+import org.argeo.eclipse.ui.utils.CommandUtils;
 import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.UserJcrUtils;
 import org.argeo.slc.SlcException;
-import org.argeo.slc.client.ui.dist.DistImages;
 import org.argeo.slc.client.ui.dist.DistPlugin;
 import org.argeo.slc.client.ui.dist.commands.CopyWorkspace;
 import org.argeo.slc.client.ui.dist.commands.CreateWorkspace;
 import org.argeo.slc.client.ui.dist.commands.DeleteWorkspace;
+import org.argeo.slc.client.ui.dist.commands.DisplayRepoInformation;
 import org.argeo.slc.client.ui.dist.commands.Fetch;
-import org.argeo.slc.client.ui.dist.commands.ManageWorkspaceAuth;
+import org.argeo.slc.client.ui.dist.commands.MergeWorkspaces;
 import org.argeo.slc.client.ui.dist.commands.NormalizeDistribution;
+import org.argeo.slc.client.ui.dist.commands.NormalizeWorkspace;
+import org.argeo.slc.client.ui.dist.commands.OpenGenerateBinariesWizard;
+import org.argeo.slc.client.ui.dist.commands.PublishWorkspace;
+import org.argeo.slc.client.ui.dist.commands.RefreshDistributionsView;
 import org.argeo.slc.client.ui.dist.commands.RegisterRepository;
+import org.argeo.slc.client.ui.dist.commands.RunInOsgi;
 import org.argeo.slc.client.ui.dist.commands.UnregisterRemoteRepo;
-import org.argeo.slc.client.ui.dist.editors.DistributionEditor;
-import org.argeo.slc.client.ui.dist.editors.DistributionEditorInput;
-import org.argeo.slc.client.ui.dist.utils.ArtifactNamesComparator;
+import org.argeo.slc.client.ui.dist.controllers.DistTreeComparator;
+import org.argeo.slc.client.ui.dist.controllers.DistTreeComparer;
+import org.argeo.slc.client.ui.dist.controllers.DistTreeContentProvider;
+import org.argeo.slc.client.ui.dist.controllers.DistTreeDoubleClickListener;
+import org.argeo.slc.client.ui.dist.controllers.DistTreeLabelProvider;
+import org.argeo.slc.client.ui.dist.model.DistParentElem;
+import org.argeo.slc.client.ui.dist.model.ModularDistBaseElem;
+import org.argeo.slc.client.ui.dist.model.RepoElem;
+import org.argeo.slc.client.ui.dist.model.WkspGroupElem;
+import org.argeo.slc.client.ui.dist.model.WorkspaceElem;
 import org.argeo.slc.client.ui.dist.utils.CommandHelpers;
 import org.argeo.slc.jcr.SlcNames;
-import org.argeo.slc.repo.RepoConstants;
-import org.argeo.slc.repo.RepoUtils;
-import org.argeo.util.security.Keyring;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.IContributionItem;
 import org.eclipse.jface.action.IMenuListener;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.MenuManager;
 import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
 import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITreeContentProvider;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.TreeViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
 import org.eclipse.jface.viewers.ViewerDropAdapter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.DND;
@@ -87,25 +70,25 @@ import org.eclipse.swt.dnd.DragSourceEvent;
 import org.eclipse.swt.dnd.TextTransfer;
 import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.dnd.TransferData;
-import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.part.ViewPart;
 
 /**
- * Browse and manipulate distributions (like merge, rename, etc.). Only support
- * one single repository currently.
+ * Browse, manipulate and manage distributions across multiple repositories
+ * (like fetch, merge, publish, etc.).
  */
 public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames {
-       private final static Log log = LogFactory.getLog(DistributionsView.class);
+       // private final static Log log =
+       // LogFactory.getLog(DistributionsView.class);
+
        public final static String ID = DistPlugin.ID + ".distributionsView";
 
+       /* DEPENDENCY INJECTION */
        private Repository nodeRepository;
-       private RepositoryFactory repositoryFactory;
-       private Keyring keyring;
+       private DistTreeContentProvider treeContentProvider;
 
        private TreeViewer viewer;
 
@@ -116,38 +99,27 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                                | SWT.FULL_SELECTION | SWT.BORDER);
 
                TreeViewerColumn col = new TreeViewerColumn(viewer, SWT.NONE);
-               col.getColumn().setWidth(200);
-               col.setLabelProvider(new ColumnLabelProvider() {
-                       @Override
-                       public String getText(Object element) {
-                               if (element instanceof RepoElem)
-                                       return ((RepoElem) element).getLabel();
-                               return element.toString();
-                       }
-
-                       @Override
-                       public Image getImage(Object element) {
-                               if (element instanceof RepoElem)
-                                       return DistImages.IMG_REPO;
-                               else if (element instanceof DistributionElem) {
-                                       return DistImages.IMG_WKSP;
-                               }
-                               return null;
-                       }
-               });
+               col.getColumn().setWidth(400);
+               col.setLabelProvider(new DistTreeLabelProvider());
 
                final Tree tree = viewer.getTree();
                tree.setHeaderVisible(false);
                tree.setLinesVisible(false);
 
-               viewer.setContentProvider(new DistributionsContentProvider());
-               viewer.addDoubleClickListener(new DistributionsDCL());
-               viewer.setComparator(new ArtifactNamesComparator());
+               // viewer.setContentProvider(new DistTreeContentProvider());
+               viewer.setContentProvider(treeContentProvider);
+               viewer.addDoubleClickListener(new DistTreeDoubleClickListener(viewer));
+               viewer.setComparer(new DistTreeComparer());
+
+               viewer.setComparator(new DistTreeComparator());
 
-               // Enable selection retrieving from outside the view
+               @SuppressWarnings("unused")
+               ViewerComparator vc = viewer.getComparator();
+
+               // Enable retrieving current tree selected items from outside the view
                getSite().setSelectionProvider(viewer);
 
-               // Drag'n drop
+               // Drag and drop
                Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
                int operations = DND.DROP_COPY | DND.DROP_MOVE;
                viewer.addDragSupport(operations, tt, new ViewDragListener());
@@ -163,44 +135,15 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                viewer.getTree().setMenu(menu);
                getSite().registerContextMenu(menuManager, viewer);
 
-               Session nodeSession = null;
-               try {
-                       nodeSession = nodeRepository.login();
-
-                       // make sure base directory is available
-                       Node repos = JcrUtils.mkdirs(nodeSession,
-                                       UserJcrUtils.getUserHome(nodeSession).getPath()
-                                                       + RepoConstants.REPOSITORIES_BASE_PATH);
-                       nodeSession.save();
-
-                       // register default local java repository
-                       String alias = RepoConstants.DEFAULT_JAVA_REPOSITORY_ALIAS;
-                       Repository javaRepository = ArgeoJcrUtils.getRepositoryByAlias(
-                                       repositoryFactory, alias);
-                       if (javaRepository != null) {
-                               if (!repos.hasNode(alias)) {
-                                       Node repoNode = repos.addNode(alias,
-                                                       ArgeoTypes.ARGEO_REMOTE_REPOSITORY);
-                                       repoNode.setProperty(ARGEO_URI, "vm:///" + alias);
-                                       repoNode.addMixin(NodeType.MIX_TITLE);
-                                       repoNode.setProperty(Property.JCR_TITLE, "Internal "
-                                                       + alias + " repository");
-                                       nodeSession.save();
-                               }
-                       }
-               } catch (RepositoryException e) {
-                       throw new SlcException("Cannot register repository", e);
-               } finally {
-                       JcrUtils.logoutQuietly(nodeSession);
-               }
-
-               viewer.setInput(nodeRepository);
+               // Initialize
+               refresh();
        }
 
        /** Programatically configure the context menu */
        protected void contextMenuAboutToShow(IMenuManager menuManager) {
                IWorkbenchWindow window = DistPlugin.getDefault().getWorkbench()
                                .getActiveWorkbenchWindow();
+
                try {
                        // Most of the implemented commands support only one selected
                        // element
@@ -211,87 +154,179 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                                        .getFirstElement();
 
                        if (firstElement instanceof TreeParent
-                                       || firstElement instanceof RepoElem) {
-                               String wsName = null;
-                               String targetRepoPath = null;
+                                       || firstElement instanceof DistParentElem) {
 
-                               // Build conditions depending on element type (repo or
-                               // distribution
-                               // for the time being)
-                               boolean isDistribElem = false; // , isRepoElem = false;
+                               String targetRepoPath = null, workspaceName = null, workspacePrefix = null;
+                               // String targetRepoUri = null;
+                               // Build conditions depending on element type
+                               boolean isDistribElem = false, isModularDistBaseElem = false, isRepoElem = false, isDistribGroupElem = false;
+                               boolean isLocal = false, isReadOnly = true;
 
-                               if (firstElement instanceof DistributionElem) {
+                               RepoElem re = null;
+
+                               if (firstElement instanceof WorkspaceElem) {
+                                       WorkspaceElem de = (WorkspaceElem) firstElement;
+                                       re = (RepoElem) de.getParent().getParent();
                                        isDistribElem = true;
-                                       wsName = ((DistributionElem) firstElement).getName();
+                                       isReadOnly = de.isReadOnly();
+                                       workspaceName = de.getWorkspaceName();
+                                       isLocal = de.inHome();
+                               } else if (firstElement instanceof RepoElem) {
+                                       re = (RepoElem) firstElement;
+                                       isRepoElem = true;
+                                       isLocal = re.inHome();
+                                       isReadOnly = re.isReadOnly();
+                               } else if (firstElement instanceof ModularDistBaseElem) {
+                                       ModularDistBaseElem mdbe = (ModularDistBaseElem) firstElement;
+                                       re = (RepoElem) mdbe.getParent().getParent().getParent();
+                                       isModularDistBaseElem = true;
+                                       isLocal = re.inHome();
+                                       isReadOnly = re.isReadOnly();
+                               } else if (firstElement instanceof WkspGroupElem) {
+                                       WkspGroupElem wge = (WkspGroupElem) firstElement;
+                                       isReadOnly = wge.isReadOnly();
+                                       isDistribGroupElem = true;
+                                       re = (RepoElem) wge.getParent();
+                                       workspacePrefix = wge.getName();
                                }
 
-                               if (firstElement instanceof RepoElem) {
-                                       Node node = ((RepoElem) firstElement).getRepoNode();
-                                       targetRepoPath = node.getPath();
+                               // TODO add case for goups
+
+                               if (re != null) {
+                                       // targetRepoUri = re.getUri();
+                                       targetRepoPath = re.getRepoNode().getPath();
                                }
 
+                               // Display repo info
+                               CommandUtils.refreshCommand(menuManager, window,
+                                               DisplayRepoInformation.ID,
+                                               DisplayRepoInformation.DEFAULT_LABEL,
+                                               DisplayRepoInformation.DEFAULT_ICON, isRepoElem
+                                                               && singleElement);
+
                                // create workspace
-                               CommandHelpers.refreshCommand(menuManager, window,
+                               Map<String, String> params = new HashMap<String, String>();
+                               params.put(CreateWorkspace.PARAM_TARGET_REPO_PATH,
+                                               targetRepoPath);
+                               params.put(CreateWorkspace.PARAM_WORKSPACE_PREFIX,
+                                               workspacePrefix);
+                               CommandUtils.refreshParametrizedCommand(menuManager, window,
                                                CreateWorkspace.ID, CreateWorkspace.DEFAULT_LABEL,
-                                               CreateWorkspace.DEFAULT_ICON_PATH, !isDistribElem
-                                                               && singleElement);
+                                               CreateWorkspace.DEFAULT_ICON,
+                                               (isRepoElem || isDistribGroupElem) && singleElement
+                                                               && !isReadOnly, params);
 
                                // Register a remote repository
-                               CommandHelpers.refreshCommand(menuManager, window,
+                               CommandUtils.refreshCommand(menuManager, window,
                                                RegisterRepository.ID,
                                                RegisterRepository.DEFAULT_LABEL,
-                                               RegisterRepository.DEFAULT_ICON_PATH, !isDistribElem
+                                               RegisterRepository.DEFAULT_ICON, isRepoElem
                                                                && singleElement);
 
                                // Unregister a remote repository
-                               Map<String, String> params = new HashMap<String, String>();
+                               params = new HashMap<String, String>();
                                params.put(UnregisterRemoteRepo.PARAM_REPO_PATH, targetRepoPath);
-                               CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                               CommandUtils.refreshParametrizedCommand(menuManager, window,
                                                UnregisterRemoteRepo.ID,
                                                UnregisterRemoteRepo.DEFAULT_LABEL,
-                                               UnregisterRemoteRepo.DEFAULT_ICON_PATH, !isDistribElem
-                                                               && singleElement, params);
+                                               UnregisterRemoteRepo.DEFAULT_ICON, isRepoElem
+                                                               && !isLocal && singleElement, params);
 
                                // Fetch repository
                                params = new HashMap<String, String>();
-                               params.put(Fetch.PARAM_TARGET_REPO, targetRepoPath);
-                               CommandHelpers.refreshParameterizedCommand(menuManager, window,
-                                               Fetch.ID, Fetch.DEFAULT_LABEL, Fetch.DEFAULT_ICON_PATH,
-                                               !isDistribElem && singleElement, params);
+                               params.put(Fetch.PARAM_TARGET_REPO_PATH, targetRepoPath);
+                               CommandUtils.refreshParametrizedCommand(menuManager, window,
+                                               Fetch.ID, Fetch.DEFAULT_LABEL, Fetch.DEFAULT_ICON,
+                                               isRepoElem && isLocal && singleElement && !isReadOnly,
+                                               params);
 
                                // Normalize workspace
                                params = new HashMap<String, String>();
-                               params.put(NormalizeDistribution.PARAM_WORKSPACE, wsName);
-                               CommandHelpers.refreshParameterizedCommand(menuManager, window,
-                                               NormalizeDistribution.ID,
-                                               NormalizeDistribution.DEFAULT_LABEL,
-                                               NormalizeDistribution.DEFAULT_ICON_PATH, isDistribElem
-                                                               && singleElement, params);
+                               params.put(NormalizeWorkspace.PARAM_TARGET_REPO_PATH,
+                                               targetRepoPath);
+                               params.put(NormalizeWorkspace.PARAM_WORKSPACE_NAME,
+                                               workspaceName);
+
+                               CommandUtils.refreshParametrizedCommand(menuManager, window,
+                                               NormalizeWorkspace.ID, "Normalize...",
+                                               NormalizeWorkspace.DEFAULT_ICON, isDistribElem
+                                                               && singleElement && !isReadOnly, params);
 
                                // Copy workspace
                                params = new HashMap<String, String>();
-                               params.put(CopyWorkspace.PARAM_WORKSPACE_NAME, wsName);
-                               CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                               params.put(CopyWorkspace.PARAM_TARGET_REPO_PATH, targetRepoPath);
+                               params.put(CopyWorkspace.PARAM_SOURCE_WORKSPACE_NAME,
+                                               workspaceName);
+                               CommandUtils.refreshParametrizedCommand(menuManager, window,
                                                CopyWorkspace.ID, CopyWorkspace.DEFAULT_LABEL,
-                                               CopyWorkspace.DEFAULT_ICON_PATH, isDistribElem
+                                               CopyWorkspace.DEFAULT_ICON, isDistribElem
                                                                && singleElement, params);
 
-                               // Delete Workspace
+                               // Clear Workspace
                                params = new HashMap<String, String>();
-                               params.put(DeleteWorkspace.PARAM_WORKSPACE_NAME, wsName);
-                               CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                               params.put(DeleteWorkspace.PARAM_TARGET_REPO_PATH,
+                                               targetRepoPath);
+                               params.put(DeleteWorkspace.PARAM_WORKSPACE_NAME, workspaceName);
+                               CommandUtils.refreshParametrizedCommand(menuManager, window,
                                                DeleteWorkspace.ID, DeleteWorkspace.DEFAULT_LABEL,
-                                               DeleteWorkspace.DEFAULT_ICON_PATH, isDistribElem
-                                                               && singleElement, params);
+                                               DeleteWorkspace.DEFAULT_ICON, isDistribElem
+                                                               && singleElement && !isReadOnly, params);
+
+                               // Advanced submenu
+                               MenuManager submenu = new MenuManager("Advanced", DistPlugin.ID
+                                               + ".advancedSubmenu");
+                               IContributionItem ici = menuManager.find(DistPlugin.ID
+                                               + ".advancedSubmenu");
+                               if (ici != null)
+                                       menuManager.remove(ici);
+
+                               // Publish workspace
+                               params = new HashMap<String, String>();
+                               params.put(PublishWorkspace.PARAM_TARGET_REPO_PATH,
+                                               targetRepoPath);
+                               params.put(PublishWorkspace.PARAM_WORKSPACE_NAME, workspaceName);
+                               CommandUtils.refreshParametrizedCommand(submenu, window,
+                                               PublishWorkspace.ID, PublishWorkspace.DEFAULT_LABEL,
+                                               PublishWorkspace.DEFAULT_ICON, isDistribElem
+                                                               && singleElement && !isReadOnly, params);
+
+                               // Normalize distribution (Legacy)
+                               params = new HashMap<String, String>();
+                               params.put(NormalizeDistribution.PARAM_TARGET_REPO_PATH,
+                                               targetRepoPath);
+                               params.put(NormalizeDistribution.PARAM_WORKSPACE_NAME,
+                                               workspaceName);
+                               CommandUtils.refreshParametrizedCommand(submenu, window,
+                                               NormalizeDistribution.ID,
+                                               NormalizeDistribution.DEFAULT_LABEL,
+                                               NormalizeDistribution.DEFAULT_ICON, isDistribElem
+                                                               && singleElement && !isReadOnly, params);
 
-                               // Manage workspace authorizations
+                               // Run in OSGi
                                params = new HashMap<String, String>();
-                               params.put(ManageWorkspaceAuth.PARAM_WORKSPACE_NAME, wsName);
-                               CommandHelpers.refreshParameterizedCommand(menuManager, window,
-                                               ManageWorkspaceAuth.ID,
-                                               ManageWorkspaceAuth.DEFAULT_LABEL,
-                                               ManageWorkspaceAuth.DEFAULT_ICON_PATH, isDistribElem
-                                                               && singleElement, params);
+                               params.put(RunInOsgi.PARAM_WORKSPACE_NAME, workspaceName);
+                               CommandUtils.refreshParametrizedCommand(submenu, window,
+                                               RunInOsgi.ID, RunInOsgi.DEFAULT_LABEL,
+                                               RunInOsgi.DEFAULT_ICON, isDistribElem && singleElement
+                                                               && isLocal, params);// Run in OSGi
+
+                               CommandUtils.refreshCommand(submenu, window,
+                                               OpenGenerateBinariesWizard.ID,
+                                               OpenGenerateBinariesWizard.DEFAULT_LABEL,
+                                               OpenGenerateBinariesWizard.DEFAULT_ICON,
+                                               isModularDistBaseElem && !isReadOnly);
+
+                               if (submenu.getSize() > 0)
+                                       menuManager.add(submenu);
+
+                               // // Manage workspace authorizations
+                               // params = new HashMap<String, String>();
+                               // params.put(ManageWorkspaceAuth.PARAM_WORKSPACE_NAME, wsName);
+                               // CommandHelpers.refreshParameterizedCommand(menuManager,
+                               // window,
+                               // ManageWorkspaceAuth.ID, ManageWorkspaceAuth.DEFAULT_LABEL,
+                               // ManageWorkspaceAuth.DEFAULT_ICON_PATH, isDistribElem
+                               // && singleElement && !isReadOnly, params);
                        }
                } catch (RepositoryException e) {
                        throw new SlcException("unexpected errror while "
@@ -308,211 +343,8 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
         * Force refresh of the whole view
         */
        public void refresh() {
-               viewer.setContentProvider(new DistributionsContentProvider());
-       }
-
-       /*
-        * INTERNAL CLASSES
-        */
-       /** Content provider */
-       private class DistributionsContentProvider implements ITreeContentProvider {
-               Session nodeSession;
-               List<RepoElem> repositories = new ArrayList<RepoElem>();
-
-               public Object[] getElements(Object input) {
-                       Repository nodeRepository = (Repository) input;
-                       try {
-                               if (nodeSession != null)
-                                       dispose();
-                               nodeSession = nodeRepository.login();
-
-                               String reposPath = UserJcrUtils.getUserHome(nodeSession)
-                                               .getPath() + RepoConstants.REPOSITORIES_BASE_PATH;
-                               NodeIterator repos = nodeSession.getNode(reposPath).getNodes();
-                               while (repos.hasNext()) {
-                                       Node repoNode = repos.nextNode();
-                                       if (repoNode.isNodeType(ArgeoTypes.ARGEO_REMOTE_REPOSITORY)) {
-                                               repositories.add(new RepoElem(repoNode));
-                                       }
-                               }
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot get base elements", e);
-                       }
-                       return repositories.toArray();
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-
-               }
-
-               public Object[] getChildren(Object parentElement) {
-                       if (parentElement instanceof RepoElem) {
-                               return ((RepoElem) parentElement).getChildren();
-                       } else if (parentElement instanceof DistributionElem) {
-                               return ((DistributionElem) parentElement).getChildren();
-                       }
-                       return null;
-               }
-
-               public Object getParent(Object element) {
-                       // TODO register repo elem in distribution elem?
-                       return null;
-               }
-
-               public boolean hasChildren(Object element) {
-                       if (element instanceof RepoElem) {
-                               return true;
-                       } else if (element instanceof DistributionElem) {
-                               return false;
-                       }
-                       return false;
-               }
-
-               public void dispose() {
-                       for (RepoElem repoElem : repositories)
-                               repoElem.dispose();
-                       repositories = new ArrayList<RepoElem>();
-                       JcrUtils.logoutQuietly(nodeSession);
-               }
-
-       }
-
-       /** A software repository */
-       private class RepoElem {
-               private Node repoNode;
-
-               private Repository repository;
-               private Credentials credentials;
-
-               public RepoElem(Node repoNode) {
-                       this.repoNode = repoNode;
-               }
-
-               /** Lazily connects to repository */
-               protected void connect() {
-                       if (repository != null)
-                               return;
-                       repository = RepoUtils.getRepository(repositoryFactory, keyring,
-                                       repoNode);
-                       credentials = RepoUtils.getRepositoryCredentials(keyring, repoNode);
-               }
-
-               public String getLabel() {
-                       try {
-                               if (repoNode.isNodeType(NodeType.MIX_TITLE)) {
-                                       return repoNode.getProperty(Property.JCR_TITLE).getString();
-                               } else {
-                                       return repoNode.getName();
-                               }
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot read label of " + repoNode, e);
-                       }
-               }
-
-               public String toString() {
-                       return repoNode.toString();
-               }
-
-               public Object[] getChildren() {
-                       connect();
-                       Session session = null;
-                       try {
-                               session = repository.login(credentials);
-                               String[] workspaceNames = session.getWorkspace()
-                                               .getAccessibleWorkspaceNames();
-                               List<DistributionElem> distributionElems = new ArrayList<DistributionElem>();
-                               for (String workspaceName : workspaceNames) {
-                                       // filter technical workspaces
-                                       // FIXME: rely on a more robust rule than just wksp name
-                                       if (workspaceName.lastIndexOf('-') > 0) {
-                                               Node workspaceNode = repoNode.hasNode(workspaceName) ? repoNode
-                                                               .getNode(workspaceName) : repoNode
-                                                               .addNode(workspaceName);
-                                               repoNode.getSession().save();
-                                               distributionElems.add(new DistributionElem(this,
-                                                               workspaceNode));
-                                               // FIXME remove deleted workspaces
-                                       }
-                               }
-                               return distributionElems.toArray();
-                       } catch (RepositoryException e) {
-                               throw new SlcException(
-                                               "Cannot list workspaces for " + repoNode, e);
-                       } finally {
-                               JcrUtils.logoutQuietly(session);
-                       }
-               }
-
-               public void dispose() {
-               }
-
-               public Node getRepoNode() {
-                       return repoNode;
-               }
-
-               public String getRepoPath() {
-                       try {
-                               return repoNode.getPath();
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot get path for " + repoNode, e);
-                       }
-               }
-
-               public Repository getRepository() {
-                       connect();
-                       return repository;
-               }
-
-               public Credentials getCredentials() {
-                       return credentials;
-               }
-
-       }
-
-       /** Abstracts a distribution, that is a workspace */
-       private static class DistributionElem extends TreeParent {
-               private final RepoElem repoElem;
-               private final Node workspaceNode;
-
-               public DistributionElem(RepoElem repoElem, Node workspaceNode) {
-                       super(JcrUtils.getNameQuietly(workspaceNode));
-                       this.repoElem = repoElem;
-                       this.workspaceNode = workspaceNode;
-               }
-
-               public Node getWorkspaceNode() {
-                       return workspaceNode;
-               }
-
-               public String getWorkspaceName() {
-                       return JcrUtils.getNameQuietly(workspaceNode);
-               }
-
-               public String getWorkspacePath() {
-                       try {
-                               return workspaceNode.getPath();
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot get or add workspace path "
-                                               + getWorkspaceName(), e);
-                       }
-               }
-
-               public String getRepoPath() {
-                       try {
-                               return workspaceNode.getParent().getPath();
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot get or add workspace path "
-                                               + getWorkspaceName(), e);
-                       }
-               }
-
-               public RepoElem getRepoElem() {
-                       return repoElem;
-               }
-
-               public Credentials getCredentials() {
-                       return repoElem.getCredentials();
-               }
+               viewer.setInput(nodeRepository);
+               viewer.expandToLevel(2);
        }
 
        /** Listens to drag */
@@ -520,11 +352,11 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                public void dragSetData(DragSourceEvent event) {
                        IStructuredSelection selection = (IStructuredSelection) viewer
                                        .getSelection();
-                       if (selection.getFirstElement() instanceof DistributionElem) {
-                               DistributionElem de = (DistributionElem) selection
-                                               .getFirstElement();
+                       if (selection.getFirstElement() instanceof WorkspaceElem) {
+                               WorkspaceElem de = (WorkspaceElem) selection.getFirstElement();
                                if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
-                                       event.data = de.getWorkspacePath();
+                                       event.data = ((RepoElem) de.getParent().getParent())
+                                                       .getUri() + "/" + de.getWorkspaceName();
                                }
                        }
                }
@@ -539,65 +371,34 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
 
                @Override
                public boolean performDrop(Object data) {
-                       DistributionElem sourceDist = (DistributionElem) getSelectedObject();
+                       WorkspaceElem sourceWksp = (WorkspaceElem) getSelectedObject();
                        RepoElem targetRepo = (RepoElem) getCurrentTarget();
 
-                       Boolean ok = MessageDialog.openConfirm(getSite().getShell(),
-                                       "Confirm distribution merge", "Do you want to merge "
-                                                       + sourceDist.getWorkspaceName() + " (from repo "
-                                                       + sourceDist.getRepoElem().getLabel()
-                                                       + ") to repo " + targetRepo.getLabel() + "?");
+                       Boolean ok = MessageDialog.openConfirm(
+                                       getSite().getShell(),
+                                       "Confirm distribution merge",
+                                       "Do you want to merge "
+                                                       + sourceWksp.getWorkspaceName()
+                                                       + " (from repo "
+                                                       + ((RepoElem) sourceWksp.getParent().getParent())
+                                                                       .getLabel() + ") to repo "
+                                                       + targetRepo.getLabel() + "?");
                        if (!ok)
                                return false;
 
                        try {
-                               String sourceWorkspace = sourceDist.getWorkspaceName();
-                               Repository sourceRepository = RepoUtils.getRepository(
-                                               repositoryFactory, keyring, sourceDist
-                                                               .getWorkspaceNode().getParent());
-                               Credentials sourceCredentials = RepoUtils
-                                               .getRepositoryCredentials(keyring, sourceDist
-                                                               .getWorkspaceNode().getParent());
-
-                               String targetWorkspace = sourceWorkspace;
-                               Repository targetRepository = RepoUtils.getRepository(
-                                               repositoryFactory, keyring, targetRepo.getRepoNode());
-                               Credentials targetCredentials = RepoUtils
-                                               .getRepositoryCredentials(keyring,
-                                                               targetRepo.getRepoNode());
-
-                               // Open sessions here since the background thread
-                               // won't necessarily be authenticated.
-                               // Job should close the sessions.
-                               Session sourceSession = sourceRepository.login(
-                                               sourceCredentials, sourceWorkspace);
-                               Session targetSession;
-                               try {
-                                       targetSession = targetRepository.login(targetCredentials,
-                                                       targetWorkspace);
-                               } catch (NoSuchWorkspaceException e) {
-                                       Session defaultSession = targetRepository
-                                                       .login(targetCredentials);
-                                       try {
-                                               defaultSession.getWorkspace().createWorkspace(
-                                                               targetWorkspace);
-                                       } catch (Exception e1) {
-                                               throw new SlcException("Cannot create new workspace "
-                                                               + targetWorkspace, e);
-                                       } finally {
-                                               JcrUtils.logoutQuietly(defaultSession);
-                                       }
-                                       targetSession = targetRepository.login(targetCredentials,
-                                                       targetWorkspace);
-                               }
-
-                               Job workspaceMergeJob = new WorkspaceMergeJob(sourceSession,
-                                               targetSession);
-                               workspaceMergeJob.setUser(true);
-                               workspaceMergeJob.schedule();
+                               Map<String, String> params = new HashMap<String, String>();
+                               params.put(MergeWorkspaces.PARAM_TARGET_REPO_PATH, targetRepo
+                                               .getRepoNode().getPath());
+                               params.put(MergeWorkspaces.PARAM_SOURCE_REPO_PATH,
+                                               ((RepoElem) sourceWksp.getParent().getParent())
+                                                               .getRepoNode().getPath());
+                               params.put(MergeWorkspaces.PARAM_SOURCE_WORKSPACE_NAME,
+                                               sourceWksp.getWorkspaceName());
+                               CommandHelpers.callCommand(RefreshDistributionsView.ID, params);
                                return true;
                        } catch (RepositoryException e) {
-                               throw new SlcException("Cannot process drop from " + sourceDist
+                               throw new SlcException("Cannot process drop from " + sourceWksp
                                                + " to " + targetRepo, e);
                        }
                }
@@ -606,106 +407,27 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                public boolean validateDrop(Object target, int operation,
                                TransferData transferType) {
                        if (target instanceof RepoElem) {
-                               if (getSelectedObject() instanceof DistributionElem) {
+                               if (getSelectedObject() instanceof WorkspaceElem) {
                                        // check if not same repository
-                                       String srcRepoPath = ((DistributionElem) getSelectedObject())
-                                                       .getRepoPath();
-                                       String targetRepoPath = ((RepoElem) target).getRepoPath();
-                                       return !targetRepoPath.equals(srcRepoPath);
+                                       String srcRepoUri = ((RepoElem) ((WorkspaceElem) getSelectedObject())
+                                                       .getParent().getParent()).getUri();
+                                       String targetRepoUri = ((RepoElem) target).getUri();
+                                       return !targetRepoUri.equals(srcRepoUri);
                                }
                        }
                        return false;
                }
        }
 
-       private static class WorkspaceMergeJob extends Job {
-               private Session sourceSession;
-               private Session targetSession;
-
-               public WorkspaceMergeJob(Session sourceSession, Session targetSession) {
-                       super("Workspace merge");
-                       this.sourceSession = sourceSession;
-                       this.targetSession = targetSession;
-               }
-
-               @Override
-               protected IStatus run(IProgressMonitor eclipseMonitor) {
-                       long begin = System.currentTimeMillis();
-                       try {
-                               Query countQuery = sourceSession
-                                               .getWorkspace()
-                                               .getQueryManager()
-                                               .createQuery("select file from [nt:file] as file",
-                                                               Query.JCR_SQL2);
-                               QueryResult result = countQuery.execute();
-                               Long expectedCount = result.getNodes().getSize();
-                               if (log.isDebugEnabled())
-                                       log.debug("Will copy " + expectedCount + " files...");
-
-                               ArgeoMonitor monitor = new EclipseArgeoMonitor(eclipseMonitor);
-                               eclipseMonitor
-                                               .beginTask("Copy files", expectedCount.intValue());
-
-                               Long count = JcrUtils.copyFiles(sourceSession.getRootNode(),
-                                               targetSession.getRootNode(), true, monitor);
-
-                               monitor.done();
-                               long duration = (System.currentTimeMillis() - begin) / 1000;// in
-                                                                                                                                                       // s
-                               if (log.isDebugEnabled())
-                                       log.debug("Copied " + count + " files in "
-                                                       + (duration / 60) + "min " + (duration % 60) + "s");
-
-                               return Status.OK_STATUS;
-                       } catch (RepositoryException e) {
-                               return new Status(IStatus.ERROR, DistPlugin.ID, "Cannot merge",
-                                               e);
-                       } finally {
-                               JcrUtils.logoutQuietly(sourceSession);
-                               JcrUtils.logoutQuietly(targetSession);
-                       }
-               }
-       }
-
-       /** Listen to double-clicks */
-       private class DistributionsDCL implements IDoubleClickListener {
-
-               public void doubleClick(DoubleClickEvent event) {
-                       if (event.getSelection() == null || event.getSelection().isEmpty())
-                               return;
-                       Object obj = ((IStructuredSelection) event.getSelection())
-                                       .getFirstElement();
-                       if (obj instanceof DistributionElem) {
-                               DistributionElem distributionElem = (DistributionElem) obj;
-                               DistributionEditorInput dei = new DistributionEditorInput(
-                                               distributionElem.getName(), distributionElem
-                                                               .getRepoElem().getRepository(),
-                                               distributionElem.getWorkspaceName(),
-                                               distributionElem.getCredentials());
-                               try {
-                                       DistPlugin.getDefault().getWorkbench()
-                                                       .getActiveWorkbenchWindow().getActivePage()
-                                                       .openEditor(dei, DistributionEditor.ID);
-                               } catch (PartInitException e) {
-                                       ErrorFeedback.show("Cannot open editor for "
-                                                       + distributionElem.getWorkspaceName(), e);
-                               }
-                       }
-               }
-       }
-
        /*
         * DEPENDENCY INJECTION
         */
-       public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
-               this.repositoryFactory = repositoryFactory;
-       }
-
-       public void setKeyring(Keyring keyring) {
-               this.keyring = keyring;
-       }
-
        public void setNodeRepository(Repository repository) {
                this.nodeRepository = repository;
        }
+
+       public void setTreeContentProvider(
+                       DistTreeContentProvider treeContentProvider) {
+               this.treeContentProvider = treeContentProvider;
+       }
 }
\ No newline at end of file