/*
* Copyright 2003-2012 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 jetbrains.mps.idea.core.library;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
import com.intellij.openapi.roots.libraries.DummyLibraryProperties;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer.LibraryLevel;
import com.intellij.openapi.vfs.VirtualFile;
import jetbrains.mps.ide.vfs.VirtualFileUtils;
import jetbrains.mps.idea.core.project.SolutionIdea;
import jetbrains.mps.project.AbstractModule;
import jetbrains.mps.project.Solution;
import jetbrains.mps.project.StubSolution;
import jetbrains.mps.smodel.ModuleFileTracker;
import jetbrains.mps.smodel.ModuleRepositoryFacade;
import jetbrains.mps.vfs.IFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.module.SModule;
import org.jetbrains.mps.openapi.module.SModuleReference;
import org.jetbrains.mps.openapi.module.SRepository;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class ModuleLibrariesUtil {
private static final String AUTO_SUFFIX = "_auto";
public static final String LIBRARY_PREFIX = "mps.";
@NotNull
public static Collection<Library> getLibraries(SModuleReference reference, Project project) {
Set<Library> libraries = new HashSet<Library>();
for (Library library : ProjectLibraryTable.getInstance(project).getLibraries()) {
if (hasModule(library, reference)) {
libraries.add(library);
}
}
return libraries;
}
private static boolean hasModule(Library library, SModuleReference reference) {
SModule module = ModuleRepositoryFacade.getInstance().getModule(reference);
return hasModule(library, module);
}
private static boolean hasModule(Library library, SModule module) {
if (!isSuitableModule(module) || !ModuleLibraryType.isModuleLibrary(library)) {
return false;
}
Solution solution = (Solution) module;
return Arrays.asList(library.getFiles(ModuleXmlRootDetector.MPS_MODULE_XML)).contains(VirtualFileUtils.getOrCreateVirtualFile(solution.getDescriptorFile()));
}
private static boolean isSuitableModule(SModule module) {
return (module instanceof Solution) && !(module instanceof SolutionIdea) && !(module instanceof StubSolution);
}
@NotNull
public static Set<SModuleReference> getModules(SRepository repository, final Library library) {
if (!ModuleLibraryType.isModuleLibrary(library)) {
return Collections.emptySet();
}
final Set<SModuleReference> modules = new HashSet<SModuleReference>();
final Set<IFile> moduleXmls = new HashSet<IFile>();
for (VirtualFile file : library.getFiles(ModuleXmlRootDetector.MPS_MODULE_XML)) {
moduleXmls.add(VirtualFileUtils.toIFile(file));
}
repository.getModelAccess().runReadAction(new Runnable() {
@Override
public void run() {
for (IFile moduleDescriptor : moduleXmls) {
SModule moduleByFile = ModuleFileTracker.getInstance().getModuleByFile(moduleDescriptor);
if (moduleByFile != null) {
modules.add(moduleByFile.getModuleReference());
}
}
}
});
return modules;
}
public static Set<SModuleReference> getModules(SRepository repository, OrderEntry... roots) {
Set<SModuleReference> modules = new HashSet<SModuleReference>();
for (OrderEntry entry : roots) {
if (entry instanceof LibraryOrderEntry) {
modules.addAll(ModuleLibrariesUtil.getModules(repository, ((LibraryOrderEntry) entry).getLibrary()));
}
}
return modules;
}
public static Library getOrCreateAutoLibrary(AbstractModule usedModule, Project project, LibrariesContainer container) {
Library library = getAutoLibrary(usedModule.getModuleReference(), project);
if (library != null) {
return library;
}
Set<VirtualFile> stubFiles = ModuleLibraryType.getModuleJars(usedModule);
IFile descriptorFile = usedModule.getDescriptorFile();
VirtualFile descriptorVirtualFile = null;
if (descriptorFile != null) {
descriptorVirtualFile = VirtualFileUtils.getOrCreateVirtualFile(descriptorFile);
}
return createAutoLibrary(usedModule.getModuleName(), stubFiles, descriptorVirtualFile, container);
}
@Nullable
private static Library getAutoLibrary(SModuleReference reference, Project project) {
String libraryName = LIBRARY_PREFIX + reference.getModuleName() + AUTO_SUFFIX;
for (Library lib : ModuleLibrariesUtil.getLibraries(reference, project)) {
if (lib.getName().equals(libraryName)) {
return lib;
}
}
return null;
}
private static Library createAutoLibrary(String moduleName, Collection<VirtualFile> libraryFiles, @Nullable VirtualFile moduleXml, LibrariesContainer container) {
String libName = LIBRARY_PREFIX + moduleName + AUTO_SUFFIX;
NewLibraryEditor editor = new NewLibraryEditor();
editor.setName(libName);
for (VirtualFile classRoot : libraryFiles) {
editor.addRoot(classRoot, OrderRootType.CLASSES);
}
if (moduleXml != null) {
editor.addRoot(moduleXml, ModuleXmlRootDetector.MPS_MODULE_XML);
}
editor.setType(ModuleLibraryType.getInstance());
editor.setProperties(new DummyLibraryProperties());
return container.createLibrary(editor, LibraryLevel.PROJECT);
}
}