All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.openapi.externalSystem.view.ExternalProjectsStructure Maven / Gradle / Ivy

/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.openapi.externalSystem.view;

import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.treeStructure.*;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;

import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author Vladislav.Soroka
 * @since 9/22/2014
 */
public class ExternalProjectsStructure extends SimpleTreeStructure {
  private final Project myProject;
  private ExternalProjectsView myExternalProjectsView;
  private final SimpleTreeBuilder myTreeBuilder;
  private RootNode myRoot;

  private final Map myNodeMapping = new THashMap();

  public ExternalProjectsStructure(Project project, SimpleTree tree) {
    myProject = project;

    configureTree(tree);

    myTreeBuilder = new SimpleTreeBuilder(tree, (DefaultTreeModel)tree.getModel(), this, null);
    Disposer.register(myProject, myTreeBuilder);
  }

  public void init(ExternalProjectsView externalProjectsView) {
    myExternalProjectsView = externalProjectsView;
    myRoot = new RootNode();
    myTreeBuilder.initRoot();
    myTreeBuilder.expand(myRoot, null);
  }

  public Project getProject() {
    return myProject;
  }

  public void updateFrom(SimpleNode node) {
    myTreeBuilder.addSubtreeToUpdateByElement(node);
  }

  public void updateUpTo(SimpleNode node) {
    SimpleNode each = node;
    while (each != null) {
      updateFrom(each);
      each = each.getParent();
    }
  }

  @Override
  public Object getRootElement() {
    return myRoot;
  }

  private static void configureTree(final SimpleTree tree) {
    tree.setRootVisible(false);
    tree.setShowsRootHandles(true);
  }

  public void accept(@NotNull SimpleNodeVisitor visitor) {
    if (myTreeBuilder.getTree() instanceof SimpleTree) {
      ((SimpleTree)myTreeBuilder.getTree()).accept(myTreeBuilder, visitor);
    }
  }

  public void select(SimpleNode node) {
    myTreeBuilder.select(node, null);
  }

  protected Class[] getVisibleNodesClasses() {
    return null;
  }

  public void updateProjects(Collection> toImport) {
    List orphanProjects = ContainerUtil.mapNotNull(
      myNodeMapping.entrySet(), new Function, String>() {
        @Override
        public String fun(Map.Entry entry) {
          return entry.getValue() instanceof ProjectNode ? entry.getKey() : null;
        }
      });
    for (DataNode each : toImport) {
      final ProjectData projectData = each.getData();
      final String projectPath = projectData.getLinkedExternalProjectPath();
      orphanProjects.remove(projectPath);

      ExternalSystemNode projectNode = findNodeFor(projectPath);

      if (projectNode instanceof ProjectNode) {
        doMergeChildrenChanges(projectNode, each, new ProjectNode(myExternalProjectsView, each));
      }
      else {
        ExternalSystemNode node = myNodeMapping.remove(projectPath);
        if (node != null) {
          SimpleNode parent = node.getParent();
          if (parent instanceof ExternalSystemNode) {
            ((ExternalSystemNode)parent).remove(projectNode);
          }
        }

        projectNode = new ProjectNode(myExternalProjectsView, each);
        myNodeMapping.put(projectPath, projectNode);
      }
      if (toImport.size() == 0) {
        myTreeBuilder.expand(projectNode, null);
      }
      doUpdateProject((ProjectNode)projectNode);
    }

    //remove orphan projects from view
    for (String orphanProjectPath : orphanProjects) {
      ExternalSystemNode projectNode = myNodeMapping.remove(orphanProjectPath);
      if (projectNode instanceof ProjectNode) {
        SimpleNode parent = projectNode.getParent();
        if (parent instanceof ExternalSystemNode) {
          ((ExternalSystemNode)parent).remove(projectNode);
          updateUpTo(projectNode);
        }
      }
    }
  }

  private void doMergeChildrenChanges(ExternalSystemNode currentNode, DataNode newDataNode, ExternalSystemNode newNode) {
    final ExternalSystemNode[] cached = currentNode.getCached();
    if (cached != null) {
      Map oldDataMap = ContainerUtil.newLinkedHashMap();
      for (ExternalSystemNode node : cached) {
        Object key = node.getData() != null ? node.getData() : node.getName();
        oldDataMap.put(key, node);
      }

      Map newDataMap = ContainerUtil.newLinkedHashMap();
      Map unchangedNewDataMap = ContainerUtil.newLinkedHashMap();
      for (ExternalSystemNode node : newNode.getChildren()) {
        Object key = node.getData() != null ? node.getData() : node.getName();
        if (oldDataMap.remove(key) == null) {
          newDataMap.put(key, node);
        }
        else {
          unchangedNewDataMap.put(key, node);
        }
      }

      currentNode.removeAll(oldDataMap.values());

      for (ExternalSystemNode node : currentNode.getChildren()) {
        Object key = node.getData() != null ? node.getData() : node.getName();
        final ExternalSystemNode unchangedNewNode = unchangedNewDataMap.get(key);
        if (unchangedNewNode != null) {
          doMergeChildrenChanges(node, unchangedNewNode.myDataNode, unchangedNewNode);
        }
      }

      updateFrom(currentNode);
      currentNode.addAll(newDataMap.values());
    }
    //noinspection unchecked
    currentNode.setDataNode(newDataNode);
  }

  private void doUpdateProject(ProjectNode node) {
    ExternalSystemNode newParentNode = myRoot;
    node.updateProject();
    reconnectNode(node, newParentNode);
  }

  private static void reconnectNode(ProjectNode node, ExternalSystemNode newParentNode) {
    ExternalSystemNode oldParentNode = node.getGroup();
    if (oldParentNode == null || !oldParentNode.equals(newParentNode)) {
      if (oldParentNode != null) {
        oldParentNode.remove(node);
      }
      newParentNode.add(node);
    }
  }

  @SuppressWarnings("SuspiciousMethodCalls")
  private ExternalSystemNode findNodeFor(String projectPath) {
    return myNodeMapping.get(projectPath);
  }

  public  void updateNodes(@NotNull Class nodeClass) {
    for (T node : getNodes(nodeClass)) {
      updateFrom(node);
    }
  }

  public  void visitNodes(@NotNull Class nodeClass, @NotNull Consumer consumer) {
    for (T node : getNodes(nodeClass)) {
      consumer.consume(node);
    }
  }

  public class RootNode extends ExternalSystemNode {
    public RootNode() {
      super(myExternalProjectsView, null, null);
    }

    @Override
    public boolean isVisible() {
      return true;
    }
  }

  public enum ErrorLevel {
    NONE, ERROR
  }

  enum DisplayKind {
    ALWAYS, NEVER, NORMAL
  }

  @NotNull
  public  List getNodes(@NotNull Class nodeClass) {
    return doGetNodes(nodeClass, myRoot.getChildren(), new SmartList());
  }

  @NotNull
  private static  List doGetNodes(@NotNull Class nodeClass,
                                                                   SimpleNode[] nodes,
                                                                   @NotNull List result) {
    if (nodes == null) return result;

    for (SimpleNode node : nodes) {
      if (nodeClass.isInstance(node)) {
        //noinspection unchecked
        result.add((T)node);
      }
      doGetNodes(nodeClass, node.getChildren(), result);
    }
    return result;
  }

  @NotNull
  public  List getSelectedNodes(SimpleTree tree, Class nodeClass) {
    final List filtered = new ArrayList();
    for (SimpleNode node : getSelectedNodes(tree)) {
      if ((nodeClass != null) && (!nodeClass.isInstance(node))) {
        filtered.clear();
        break;
      }
      //noinspection unchecked
      filtered.add((T)node);
    }
    return filtered;
  }

  private static List getSelectedNodes(SimpleTree tree) {
    List nodes = new ArrayList();
    TreePath[] treePaths = tree.getSelectionPaths();
    if (treePaths != null) {
      for (TreePath treePath : treePaths) {
        nodes.add(tree.getNodeFor(treePath));
      }
    }
    return nodes;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy