package jetbrains.mps.jps.project;
import com.intellij.openapi.util.io.FileUtil;
import jetbrains.mps.extapi.module.ModuleFacetBase;
import jetbrains.mps.extapi.persistence.FileDataSource;
import jetbrains.mps.idea.core.make.MPSMakeConstants;
import jetbrains.mps.idea.core.project.JpsModelRootContributor;
import jetbrains.mps.jps.build.MPSCompilerUtil;
import jetbrains.mps.jps.model.JpsMPSRepositoryFacade;
import jetbrains.mps.module.SDependencyImpl;
import jetbrains.mps.persistence.FilePerRootDataSource;
import jetbrains.mps.project.ModuleId;
import jetbrains.mps.project.Solution;
import jetbrains.mps.project.facets.JavaModuleFacet;
import jetbrains.mps.project.facets.JavaModuleFacetImpl;
import jetbrains.mps.project.structure.modules.SolutionDescriptor;
import jetbrains.mps.vfs.FileSystem;
import jetbrains.mps.vfs.IFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.messages.BuildMessage.Kind;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.java.JpsJavaSdkType;
import org.jetbrains.jps.model.library.JpsLibrary;
import org.jetbrains.jps.model.module.JpsDependencyElement;
import org.jetbrains.jps.model.module.JpsLibraryDependency;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.module.JpsModuleDependency;
import org.jetbrains.jps.model.module.JpsSdkDependency;
import org.jetbrains.jps.service.JpsServiceManager;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.module.SDependency;
import org.jetbrains.mps.openapi.module.SDependencyScope;
import org.jetbrains.mps.openapi.persistence.DataSource;
import org.jetbrains.mps.openapi.persistence.Memento;
import org.jetbrains.mps.openapi.persistence.ModelRoot;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* danilla 12/10/12
*/
public class JpsSolutionIdea extends Solution {
private JpsModule myModule;
private Set<ModelRoot> myContributedModelRoots;
private CompileContext myCompileContext;
private AtomicReference<Map<String, SModel>> myPathToModel = new AtomicReference<Map<String, SModel>>();
public JpsSolutionIdea(@NotNull JpsModule module, SolutionDescriptor descriptor, CompileContext compileCtx) {
super(descriptor, null);
myModule = module;
myModule = module;
myCompileContext = compileCtx;
}
public JpsModule getModule() {
return myModule;
}
public SModel getModelByPath(String path) {
Map<String, SModel> map = myPathToModel.get();
if (map != null) {
return map.get(path);
}
map = new HashMap<String, SModel>();
for (SModel m : getModels()) {
DataSource source = m.getSource();
if (source instanceof FileDataSource) {
String p = ((FileDataSource) source).getFile().getPath();
p = FileUtil.toCanonicalPath(p);
map.put(p, m);
} else if(source instanceof FilePerRootDataSource) {
String p = ((FilePerRootDataSource) source).getFolder().getDescendant(".model").getPath();
p = FileUtil.toCanonicalPath(p);
map.put(p, m);
}
}
myPathToModel.compareAndSet(null, map);
return map.get(path);
}
@Override
public boolean isPackaged() {
return false;
}
@Override
public Iterable<SDependency> getDeclaredDependencies() {
List<SDependency> dependencies = new ArrayList<SDependency>();
MPSCompilerUtil.debug(myCompileContext, "^^^^ getDependencies for " + myModule.getName());
for (JpsDependencyElement jpsDep : myModule.getDependenciesList().getDependencies()) {
Solution solution = null;
if (jpsDep instanceof JpsModuleDependency) {
JpsModule jpsModule = ((JpsModuleDependency) jpsDep).getModule();
solution = JpsMPSRepositoryFacade.getInstance().getSolution(jpsModule);
} else if (jpsDep instanceof JpsLibraryDependency) {
MPSCompilerUtil.debug(myCompileContext, "**** lib dep: " + ((JpsLibraryDependency) jpsDep).getLibraryReference().getLibraryName());
JpsLibrary lib = ((JpsLibraryDependency) jpsDep).getLibrary();
if (lib == null) {
MPSCompilerUtil.debug(myCompileContext, "**** not found lib dep: " + ((JpsLibraryDependency) jpsDep).getLibraryReference().getLibraryName());
} else {
String name = lib.getName();
solution = (Solution) getRepository().getModule(ModuleId.foreign(name));
}
} else if (jpsDep instanceof JpsSdkDependency) {
MPSCompilerUtil.debug(myCompileContext, "**** jdk dep: " + ((JpsSdkDependency) jpsDep).getSdkReference().getSdkName());
if (((JpsSdkDependency) jpsDep).getSdkType().equals(JpsJavaSdkType.INSTANCE)) {
// do nothing, since we store SDK with a special module id (JDK module id, which is pulled in by use baseLanguage)
// FIXME OR put JDK module id?
continue;
}
String sdkName = ((JpsSdkDependency) jpsDep).getSdkReference().getSdkName();
solution = (Solution) getRepository().getModule(ModuleId.foreign(sdkName));
}
if (solution != null) {
dependencies.add(new SDependencyImpl(solution, SDependencyScope.DEFAULT, false));
}
}
return dependencies;
}
@Override
protected ModuleFacetBase setupFacet(ModuleFacetBase facet, Memento memento) {
if (facet instanceof JavaModuleFacet) {
facet = new JavaModuleFacetImpl() {
@Override
public IFile getClassesGen() {
IFile descriptorFile = getDescriptorFile();
if (descriptorFile != null && descriptorFile.isReadOnly()) {
myCompileContext.processMessage(new CompilerMessage(MPSMakeConstants.BUILDER_ID, Kind.INFO, " super.ClassesGen " + super.getClassesGen()));
return super.getClassesGen();
}
// FIX hard-coded forTests=false
// TODO use ProjectPaths.getModuleOutputDir(myModule, false); (using JpsJavaExtensionService directly to be compatible with IDEA 12.0.0 release)
File outputDir = JpsJavaExtensionService.getInstance().getOutputDirectory(myModule, false);
if (outputDir == null) return null;
MPSCompilerUtil.debug(myCompileContext, " ClassesGen from module " + outputDir.getPath());
return FileSystem.getInstance().getFileByPath(outputDir.getPath());
}
};
}
return super.setupFacet(facet, memento);
}
@Override
protected Iterable<ModelRoot> loadRoots() {
if (myContributedModelRoots == null) {
myContributedModelRoots = new HashSet<ModelRoot>();
for (JpsModelRootContributor c : JpsServiceManager.getInstance().getExtensions(JpsModelRootContributor.class)) {
for (ModelRoot root : c.getModelRoots(myModule)) {
myContributedModelRoots.add(root);
}
}
}
List<ModelRoot> sum = new ArrayList<ModelRoot>();
for (ModelRoot mr : super.loadRoots()) {
sum.add(mr);
}
sum.addAll(myContributedModelRoots);
return sum;
}
}