private Couple<CheckedTreeNode> createRoot() {
    final Map<DataNode<?>, DataNodeCheckedTreeNode> treeNodeMap = new IdentityHashMap<>();
    final Map<String, DataNode<?>> ideGroupingMap = new TreeMap<>(); // need order for assigning parents

    final DataNodeCheckedTreeNode[] preselectedNode = {null};
    final DataNodeCheckedTreeNode[] rootModuleNode = {null};

    final MultiMap<String, String> moduleDependenciesMap = MultiMap.create();
    final Map<String, DataNode<Identifiable>> modulesNodeMap = new HashMap<>();

    for (DataNode<ModuleDependencyData> moduleDependencyDataNode : ExternalSystemApiUtil.findAllRecursively(
      myProjectInfo.getExternalProjectStructure(), ProjectKeys.MODULE_DEPENDENCY)) {
      final ModuleDependencyData moduleDependencyData = moduleDependencyDataNode.getData();
      moduleDependenciesMap.putValue(
        moduleDependencyData.getOwnerModule().getId(),
        moduleDependencyData.getTarget().getId());
    }

    final int[] modulesCount = {0};

    ExternalSystemApiUtil.visit(myProjectInfo.getExternalProjectStructure(), node -> {
      final Key key = node.getKey();
      if (!myPublicKeys.contains(key)) return;

      DataNode modifiableDataNode = getModifiableDataNode(node);

      if (myDependencyAwareDataKeys.contains(key)) {
        modulesCount[0]++;
      }

      if (modifiableDataNode.isIgnored() && myShowSelectedRowsOnly) return;

      DataNodeCheckedTreeNode treeNode = treeNodeMap.get(node);
      if (treeNode == null) {
        treeNode = new DataNodeCheckedTreeNode(node);

        if (myDependencyAwareDataKeys.contains(key)) {
          final Identifiable moduleData = (Identifiable)node.getData();
          //noinspection unchecked
          modulesNodeMap.put(moduleData.getId(), (DataNode<Identifiable>)node);
        }

        if (myPreselectedNodeObject != null && myPreselectedNodeObject.equals(node.getData())) {
          preselectedNode[0] = treeNode;
        }
        if (node.getData() instanceof ModuleData moduleData) {
          if (key.equals(ProjectKeys.MODULE) && myProjectInfo.getExternalProjectPath().equals(moduleData.getLinkedExternalProjectPath())) {
            rootModuleNode[0] = treeNode;
          }
          String ideGrouping = moduleData.getIdeGrouping();
          ideGroupingMap.put(ideGrouping, node);
        } else {
          // add elements under module node like web/enterprise artifacts
          DataNode<ModuleData> parentModule = node.getParent(ModuleData.class);
          if(parentModule != null) {
            DataNodeCheckedTreeNode moduleTreeNode = treeNodeMap.get(parentModule);
            if(moduleTreeNode != null) {
              moduleTreeNode.add(treeNode);
              treeNode.setParent(moduleTreeNode);
            }
          }
        }
        treeNode.setEnabled(myIgnorableKeys.contains(key));
        treeNodeMap.put(node, treeNode);
      }
    });

    for (Map.Entry<String, DataNode<?>> groupingEntry : ideGroupingMap.entrySet()) {
      DataNode node = groupingEntry.getValue();
      if (!(node.getData() instanceof ModuleData moduleData)) continue;
      String ideParentGrouping = moduleData.getIdeParentGrouping();
      DataNode structuralParent = ideParentGrouping != null ? ideGroupingMap.get(ideParentGrouping) : null;
      DataNodeCheckedTreeNode treeParentNode = structuralParent != null ? treeNodeMap.get(structuralParent) : null;

      DataNodeCheckedTreeNode treeNode = treeNodeMap.get(node);

      if (treeParentNode == null) {
        treeParentNode = treeNodeMap.get(node.getParent());
      }

      if (treeNode == null || treeParentNode == null) continue;

      treeParentNode.add(treeNode);
      treeNode.setParent(treeParentNode);
    }

    myModulesCount = modulesCount[0];

    dependentNodeMap.clear();
    for (String moduleId : moduleDependenciesMap.keySet()) {
      final Collection<String> moduleDependencies = moduleDependenciesMap.get(moduleId);
      final DataNode<Identifiable> moduleNode = modulesNodeMap.get(moduleId);
      if (moduleNode != null) {
        dependentNodeMap.putValues(moduleNode, ContainerUtil.mapNotNull(moduleDependencies, modulesNodeMap::get));
      }
    }

    final CheckedTreeNode root = new CheckedTreeNode(null);
    final DataNodeCheckedTreeNode projectNode = treeNodeMap.get(myProjectInfo.getExternalProjectStructure());

    String rootModuleComment = ExternalSystemBundle.message("external.project.structure.project.root.module");
    if (rootModuleNode[0] != null && projectNode != null) {
      rootModuleNode[0].comment = rootModuleComment;
      if (!projectNode.isNodeChild(rootModuleNode[0])) {
        projectNode.add(rootModuleNode[0]);
      }
    }

    List<TreeNode> nodes = projectNode != null ? TreeUtil.listChildren(projectNode) : ContainerUtil.emptyList();
    nodes.sort((o1, o2) -> {
      if (o1 instanceof DataNodeCheckedTreeNode && o2 instanceof DataNodeCheckedTreeNode) {
        if (rootModuleComment.equals(((DataNodeCheckedTreeNode)o1).comment)) return -1;
        if (rootModuleComment.equals(((DataNodeCheckedTreeNode)o2).comment)) return 1;
        return StringUtil.naturalCompare(((DataNodeCheckedTreeNode)o1).text, ((DataNodeCheckedTreeNode)o2).text);
      }
      return 0;
    });
    TreeUtil.addChildrenTo(root, nodes);
    return Couple.of(root, preselectedNode[0]);
  }
private Couple<CheckedTreeNode> createRoot()