private void importMissingProjectLibraries(
     @NotNull Module module,
     @NotNull Collection<DataNode<LibraryDependencyData>> nodesToImport,
     boolean synchronous) {
   LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(module.getProject());
   List<DataNode<LibraryData>> librariesToImport = ContainerUtilRt.newArrayList();
   for (DataNode<LibraryDependencyData> dataNode : nodesToImport) {
     final LibraryDependencyData dependencyData = dataNode.getData();
     if (dependencyData.getLevel() != LibraryLevel.PROJECT) {
       continue;
     }
     final Library library = libraryTable.getLibraryByName(dependencyData.getName());
     if (library == null) {
       DataNode<ProjectData> projectNode = dataNode.getDataNode(ProjectKeys.PROJECT);
       if (projectNode != null) {
         DataNode<LibraryData> libraryNode =
             ExternalSystemApiUtil.find(
                 projectNode,
                 ProjectKeys.LIBRARY,
                 new BooleanFunction<DataNode<LibraryData>>() {
                   @Override
                   public boolean fun(DataNode<LibraryData> node) {
                     return node.getData().equals(dependencyData.getTarget());
                   }
                 });
         if (libraryNode != null) {
           librariesToImport.add(libraryNode);
         }
       }
     }
   }
   if (!librariesToImport.isEmpty()) {
     myLibraryManager.importData(librariesToImport, module.getProject(), synchronous);
   }
 }
 private void syncExistingAndRemoveObsolete(
     @NotNull IdeModifiableModelsProvider modelsProvider,
     @NotNull Map<Set<String>, LibraryDependencyData> moduleLibrariesToImport,
     @NotNull Map<String, LibraryDependencyData> projectLibrariesToImport,
     @NotNull Set<LibraryDependencyData> toImport,
     @NotNull Map<OrderEntry, OrderAware> orderEntryDataMap,
     @NotNull ModifiableRootModel moduleRootModel,
     boolean hasUnresolvedLibraries) {
   for (OrderEntry entry : moduleRootModel.getOrderEntries()) {
     if (entry instanceof ModuleLibraryOrderEntryImpl) {
       ModuleLibraryOrderEntryImpl moduleLibraryOrderEntry = (ModuleLibraryOrderEntryImpl) entry;
       Library library = moduleLibraryOrderEntry.getLibrary();
       if (library == null) {
         LOG.warn(
             "Skipping module-level library entry because it doesn't have backing Library object. Entry: "
                 + entry);
         continue;
       }
       final VirtualFile[] libraryFiles = library.getFiles(OrderRootType.CLASSES);
       final Set<String> moduleLibraryKey = ContainerUtilRt.newHashSet(libraryFiles.length);
       for (VirtualFile file : libraryFiles) {
         moduleLibraryKey.add(
             ExternalSystemApiUtil.getLocalFileSystemPath(file)
                 + moduleLibraryOrderEntry.getScope().name());
       }
       LibraryDependencyData existing = moduleLibrariesToImport.remove(moduleLibraryKey);
       if (existing == null || !StringUtil.equals(existing.getInternalName(), library.getName())) {
         moduleRootModel.removeOrderEntry(entry);
       } else {
         orderEntryDataMap.put(entry, existing);
         syncExistingLibraryDependency(
             modelsProvider,
             existing,
             library,
             moduleRootModel,
             moduleLibraryOrderEntry.getOwnerModule());
         toImport.remove(existing);
       }
     } else if (entry instanceof LibraryOrderEntry) {
       LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry) entry;
       String libraryName = libraryOrderEntry.getLibraryName();
       LibraryDependencyData existing =
           projectLibrariesToImport.remove(libraryName + libraryOrderEntry.getScope().name());
       if (existing != null) {
         toImport.remove(existing);
         orderEntryDataMap.put(entry, existing);
       } else if (!hasUnresolvedLibraries) {
         // There is a possible case that a project has been successfully imported from external
         // model and after
         // that network/repo goes down. We don't want to drop existing binary mappings then.
         moduleRootModel.removeOrderEntry(entry);
       }
     }
   }
 }
 private static void setLibraryScope(
     @NotNull LibraryOrderEntry orderEntry,
     @NotNull Library lib,
     @NotNull Module module,
     @NotNull LibraryDependencyData dependencyData) {
   orderEntry.setExported(dependencyData.isExported());
   orderEntry.setScope(dependencyData.getScope());
   LOG.debug(
       String.format(
           "Configuring library '%s' of module '%s' to be%s exported and have scope %s",
           lib,
           module.getName(),
           dependencyData.isExported() ? " not" : "",
           dependencyData.getScope()));
 }
 private void importMissing(
     @NotNull Set<LibraryDependencyData> toImport,
     @NotNull ModifiableRootModel moduleRootModel,
     @NotNull LibraryTable moduleLibraryTable,
     @NotNull LibraryTable libraryTable,
     @NotNull Module module) {
   for (LibraryDependencyData dependencyData : toImport) {
     LibraryData libraryData = dependencyData.getTarget();
     if (libraryData.isUnresolved()) {
       continue;
     }
     switch (dependencyData.getLevel()) {
       case MODULE:
         @SuppressWarnings("ConstantConditions")
         Library moduleLib = moduleLibraryTable.createLibrary(dependencyData.getName());
         Library.ModifiableModel libModel = moduleLib.getModifiableModel();
         try {
           Map<OrderRootType, Collection<File>> files =
               myLibraryManager.prepareLibraryFiles(libraryData);
           myLibraryManager.registerPaths(files, libModel, dependencyData.getName());
         } finally {
           libModel.commit();
         }
         break;
       case PROJECT:
         final Library projectLib = libraryTable.getLibraryByName(dependencyData.getName());
         if (projectLib == null) {
           assert false;
           continue;
         }
         LibraryOrderEntry orderEntry = moduleRootModel.addLibraryEntry(projectLib);
         LOG.info(
             String.format(
                 "Adding library dependency '%s' to module '%s'",
                 projectLib.getName(), module.getName()));
         orderEntry.setExported(dependencyData.isExported());
         orderEntry.setScope(dependencyData.getScope());
         LOG.info(
             String.format(
                 "Configuring library dependency '%s' of module '%s' to be%s exported and have scope %s",
                 projectLib.getName(),
                 module.getName(),
                 dependencyData.isExported() ? " not" : "",
                 dependencyData.getScope()));
     }
   }
 }
  private LibraryOrderEntry syncExistingLibraryDependency(
      @NotNull IdeModifiableModelsProvider modelsProvider,
      @NotNull final LibraryDependencyData libraryDependencyData,
      @NotNull final Library library,
      @NotNull final ModifiableRootModel moduleRootModel,
      @NotNull final Module module) {
    final Library.ModifiableModel libraryModel = modelsProvider.getModifiableLibraryModel(library);
    final String libraryName = libraryDependencyData.getInternalName();
    Map<OrderRootType, Collection<File>> files =
        myLibraryManager.prepareLibraryFiles(libraryDependencyData.getTarget());
    myLibraryManager.registerPaths(files, libraryModel, libraryName);
    LibraryOrderEntry orderEntry =
        findLibraryOrderEntry(moduleRootModel, library, libraryDependencyData.getScope());

    assert orderEntry != null;
    setLibraryScope(orderEntry, library, module, libraryDependencyData);
    return orderEntry;
  }
 private void importMissing(
     @NotNull IdeModifiableModelsProvider modelsProvider,
     @NotNull Set<LibraryDependencyData> toImport,
     @NotNull Map<OrderEntry, OrderAware> orderEntryDataMap,
     @NotNull ModifiableRootModel moduleRootModel,
     @NotNull LibraryTable moduleLibraryTable,
     @NotNull Module module) {
   for (final LibraryDependencyData dependencyData : toImport) {
     final LibraryData libraryData = dependencyData.getTarget();
     final String libraryName = libraryData.getInternalName();
     switch (dependencyData.getLevel()) {
       case MODULE:
         final Library moduleLib;
         if (libraryName.isEmpty()) {
           moduleLib = moduleLibraryTable.createLibrary();
         } else {
           moduleLib = moduleLibraryTable.createLibrary(libraryName);
         }
         final LibraryOrderEntry existingLibraryDependency =
             syncExistingLibraryDependency(
                 modelsProvider, dependencyData, moduleLib, moduleRootModel, module);
         orderEntryDataMap.put(existingLibraryDependency, dependencyData);
         break;
       case PROJECT:
         final Library projectLib = modelsProvider.getLibraryByName(libraryName);
         if (projectLib == null) {
           final LibraryOrderEntry existingProjectLibraryDependency =
               syncExistingLibraryDependency(
                   modelsProvider,
                   dependencyData,
                   moduleLibraryTable.createLibrary(libraryName),
                   moduleRootModel,
                   module);
           orderEntryDataMap.put(existingProjectLibraryDependency, dependencyData);
           break;
         }
         LibraryOrderEntry orderEntry = moduleRootModel.addLibraryEntry(projectLib);
         orderEntryDataMap.put(orderEntry, dependencyData);
         setLibraryScope(orderEntry, projectLib, module, dependencyData);
     }
   }
 }
  @Override
  protected Map<OrderEntry, OrderAware> importData(
      @NotNull final Collection<DataNode<LibraryDependencyData>> nodesToImport,
      @NotNull final Module module,
      @NotNull final IdeModifiableModelsProvider modelsProvider) {
    // The general idea is to import all external project library dependencies and module libraries
    // which don't present at the
    // ide side yet and remove all project library dependencies and module libraries which present
    // at the ide but not at
    // the given collection.
    // The trick is that we should perform module settings modification inside try/finally block
    // against target root model.
    // That means that we need to prepare all necessary data, obtain a model and modify it as
    // necessary.
    final Map<Set<String> /* library paths */, LibraryDependencyData> moduleLibrariesToImport =
        ContainerUtilRt.newHashMap();
    final Map<String /* library name + scope */, LibraryDependencyData> projectLibrariesToImport =
        ContainerUtilRt.newHashMap();
    final Set<LibraryDependencyData> toImport = ContainerUtilRt.newLinkedHashSet();
    final Map<OrderEntry, OrderAware> orderEntryDataMap = ContainerUtil.newLinkedHashMap();

    boolean hasUnresolved = false;
    for (DataNode<LibraryDependencyData> dependencyNode : nodesToImport) {
      LibraryDependencyData dependencyData = dependencyNode.getData();
      LibraryData libraryData = dependencyData.getTarget();
      hasUnresolved |= libraryData.isUnresolved();
      switch (dependencyData.getLevel()) {
        case MODULE:
          Set<String> paths = ContainerUtilRt.newHashSet();
          for (String path : libraryData.getPaths(LibraryPathType.BINARY)) {
            paths.add(
                ExternalSystemApiUtil.toCanonicalPath(path) + dependencyData.getScope().name());
          }
          moduleLibrariesToImport.put(paths, dependencyData);
          toImport.add(dependencyData);
          break;
        case PROJECT:
          projectLibrariesToImport.put(
              libraryData.getInternalName() + dependencyData.getScope().name(), dependencyData);
          toImport.add(dependencyData);
      }
    }

    final boolean finalHasUnresolved = hasUnresolved;

    final ModifiableRootModel modifiableRootModel = modelsProvider.getModifiableRootModel(module);
    LibraryTable moduleLibraryTable = modifiableRootModel.getModuleLibraryTable();
    syncExistingAndRemoveObsolete(
        modelsProvider,
        moduleLibrariesToImport,
        projectLibrariesToImport,
        toImport,
        orderEntryDataMap,
        modifiableRootModel,
        finalHasUnresolved);
    // Import missing library dependencies.
    if (!toImport.isEmpty()) {
      importMissing(
          modelsProvider,
          toImport,
          orderEntryDataMap,
          modifiableRootModel,
          moduleLibraryTable,
          module);
    }
    return orderEntryDataMap;
  }