@Override
    public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
      if (externalProject == null) {
        return;
      }
      Collection<DataNode<ModuleData>> moduleNodes =
          ExternalSystemApiUtil.findAll(externalProject, ProjectKeys.MODULE);
      for (DataNode<ModuleData> node : moduleNodes) {
        myExternalModulePaths.add(node.getData().getLinkedExternalProjectPath());
      }
      ExternalSystemApiUtil.executeProjectChangeAction(
          true,
          new DisposeAwareProjectChange(myProject) {
            @Override
            public void execute() {
              ProjectRootManagerEx.getInstanceEx(myProject)
                  .mergeRootsChangesDuring(
                      new Runnable() {
                        @Override
                        public void run() {
                          myProjectDataManager.importData(
                              externalProject.getKey(),
                              Collections.singleton(externalProject),
                              myProject,
                              true);
                        }
                      });

              processOrphanProjectLibraries();
            }
          });
      if (--myCounter[0] <= 0) {
        processOrphanModules();
      }
    }
  /**
   * Allows to answer if given ide project has 1-1 mapping with the given external project, i.e. the
   * ide project has been imported from external system and no other external projects have been
   * added.
   *
   * <p>This might be necessary in a situation when project-level setting is changed (e.g. project
   * name). We don't want to rename ide project if it doesn't completely corresponds to the given
   * ide project then.
   *
   * @param ideProject target ide project
   * @param externalProject target external project
   * @return <code>true</code> if given ide project has 1-1 mapping to the given external project;
   *     <code>false</code> otherwise
   */
  public static boolean isOneToOneMapping(
      @NotNull Project ideProject, @NotNull DataNode<ProjectData> externalProject) {
    String linkedExternalProjectPath = null;
    for (ExternalSystemManager<?, ?, ?, ?, ?> manager : ExternalSystemApiUtil.getAllManagers()) {
      ProjectSystemId externalSystemId = manager.getSystemId();
      AbstractExternalSystemSettings systemSettings =
          ExternalSystemApiUtil.getSettings(ideProject, externalSystemId);
      Collection projectsSettings = systemSettings.getLinkedProjectsSettings();
      int linkedProjectsNumber = projectsSettings.size();
      if (linkedProjectsNumber > 1) {
        // More than one external project of the same external system type is linked to the given
        // ide project.
        return false;
      } else if (linkedProjectsNumber == 1) {
        if (linkedExternalProjectPath == null) {
          // More than one external project of different external system types is linked to the
          // current ide project.
          linkedExternalProjectPath =
              ((ExternalProjectSettings) projectsSettings.iterator().next())
                  .getExternalProjectPath();
        } else {
          return false;
        }
      }
    }

    ProjectData projectData = externalProject.getData();
    if (linkedExternalProjectPath != null
        && !linkedExternalProjectPath.equals(projectData.getLinkedExternalProjectPath())) {
      // New external project is being linked.
      return false;
    }

    Set<String> externalModulePaths = ContainerUtilRt.newHashSet();
    for (DataNode<ModuleData> moduleNode :
        ExternalSystemApiUtil.findAll(externalProject, ProjectKeys.MODULE)) {
      externalModulePaths.add(moduleNode.getData().getLinkedExternalProjectPath());
    }
    externalModulePaths.remove(linkedExternalProjectPath);

    PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
    for (Module module : platformFacade.getModules(ideProject)) {
      String path = module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY);
      if (!StringUtil.isEmpty(path) && !externalModulePaths.remove(path)) {
        return false;
      }
    }
    return externalModulePaths.isEmpty();
  }
    private void processOrphanProjectLibraries() {
      PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
      List<Library> orphanIdeLibraries = ContainerUtilRt.newArrayList();

      LibraryTable projectLibraryTable = platformFacade.getProjectLibraryTable(myProject);
      for (Library library : projectLibraryTable.getLibraries()) {
        if (!ExternalSystemApiUtil.isExternalSystemLibrary(library, myExternalSystemId)) continue;
        if (ProjectStructureHelper.isOrphanProjectLibrary(
            library, platformFacade.getModules(myProject))) {
          orphanIdeLibraries.add(library);
        }
      }
      for (Library orphanIdeLibrary : orphanIdeLibraries) {
        projectLibraryTable.removeLibrary(orphanIdeLibrary);
      }
    }
  /**
   * Is expected to be called when given task info is about to be executed.
   *
   * <p>Basically, this method updates recent tasks list at the corresponding external system tool
   * window and persists new recent tasks state.
   *
   * @param taskInfo task which is about to be executed
   * @param project target project
   */
  public static void updateRecentTasks(
      @NotNull ExternalTaskExecutionInfo taskInfo, @NotNull Project project) {
    ProjectSystemId externalSystemId = taskInfo.getSettings().getExternalSystemId();
    ExternalSystemRecentTasksList recentTasksList =
        getToolWindowElement(
            ExternalSystemRecentTasksList.class,
            project,
            ExternalSystemDataKeys.RECENT_TASKS_LIST,
            externalSystemId);
    if (recentTasksList == null) {
      return;
    }
    recentTasksList.setFirst(taskInfo);

    ExternalSystemManager<?, ?, ?, ?, ?> manager =
        ExternalSystemApiUtil.getManager(externalSystemId);
    assert manager != null;
    AbstractExternalSystemLocalSettings settings = manager.getLocalSettingsProvider().fun(project);
    settings.setRecentTasks(recentTasksList.getModel().getTasks());
  }
  /**
   * Asks to refresh all external projects of the target external system linked to the given ide
   * project based on provided spec
   *
   * @param specBuilder import specification builder
   */
  public static void refreshProjects(@NotNull final ImportSpecBuilder specBuilder) {
    ImportSpec spec = specBuilder.build();

    ExternalSystemManager<?, ?, ?, ?, ?> manager =
        ExternalSystemApiUtil.getManager(spec.getExternalSystemId());
    if (manager == null) {
      return;
    }
    AbstractExternalSystemSettings<?, ?, ?> settings =
        manager.getSettingsProvider().fun(spec.getProject());
    final Collection<? extends ExternalProjectSettings> projectsSettings =
        settings.getLinkedProjectsSettings();
    if (projectsSettings.isEmpty()) {
      return;
    }

    final ProjectDataManager projectDataManager =
        ServiceManager.getService(ProjectDataManager.class);
    final int[] counter = new int[1];

    ExternalProjectRefreshCallback callback =
        new MyMultiExternalProjectRefreshCallback(
            spec.getProject(), projectDataManager, counter, spec.getExternalSystemId());

    Map<String, Long> modificationStamps =
        manager
            .getLocalSettingsProvider()
            .fun(spec.getProject())
            .getExternalConfigModificationStamps();
    Set<String> toRefresh = ContainerUtilRt.newHashSet();
    for (ExternalProjectSettings setting : projectsSettings) {

      // don't refresh project when auto-import is disabled if such behavior needed (e.g. on project
      // opening when auto-import is disabled)
      if (!setting.isUseAutoImport() && spec.isWhenAutoImportEnabled()) continue;

      if (spec.isForceWhenUptodate()) {
        toRefresh.add(setting.getExternalProjectPath());
      } else {
        Long oldModificationStamp = modificationStamps.get(setting.getExternalProjectPath());
        long currentModificationStamp = getTimeStamp(setting, spec.getExternalSystemId());
        if (oldModificationStamp == null || oldModificationStamp < currentModificationStamp) {
          toRefresh.add(setting.getExternalProjectPath());
        }
      }
    }

    if (!toRefresh.isEmpty()) {
      ExternalSystemNotificationManager.getInstance(spec.getProject())
          .clearNotifications(null, NotificationSource.PROJECT_SYNC, spec.getExternalSystemId());

      counter[0] = toRefresh.size();
      for (String path : toRefresh) {
        refreshProject(
            spec.getProject(),
            spec.getExternalSystemId(),
            path,
            callback,
            false,
            spec.getProgressExecutionMode());
      }
    }
  }