package org.fandev.module.wizard;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.SourcePathsBuilder;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleWithNameAlreadyExists;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectJdksModel;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.fandev.module.FanModuleSettings;
import org.fandev.module.FanModuleType;
import org.fandev.module.pod.PodFileParser;
import org.fandev.module.pod.PodModel;
import org.fandev.sdk.FanSdkType;
import org.fandev.index.FanIndex;
import org.fandev.utils.FanUtil;
import org.fandev.utils.TextUtil;
import org.fandev.utils.VirtualFileUtil;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author Dror Bereznitsky
* @date Jan 19, 2009 9:58:28 AM
*/
public class FanModuleBuilder extends ModuleBuilder implements SourcePathsBuilder {
private List<Pair<String, String>> mySourcePaths = new ArrayList<Pair<String, String>>();
private String myContentRootPath;
private Sdk mySdk;
private PodModel modulePod;
private final List<Pair<String, String>> myModuleLibraries = new ArrayList<Pair<String, String>>();
@NotNull
@Override
public Module createModule(final ModifiableModuleModel moduleModel) throws InvalidDataException, IOException, ModuleWithNameAlreadyExists, JDOMException, ConfigurationException {
final Module myModule = super.createModule(moduleModel);
final VirtualFile v = VirtualFileUtil.refreshAndFindFileByLocalPath(VirtualFileUtil.buildUrl(myContentRootPath , PodModel.BUILD_FAN));
FanModuleSettings.getInstance(myModule).setBuildScript(v);
if (modulePod != null) {
modulePod.setBuildScriptFile(v);
modulePod.setBuildScriptName(PodModel.BUILD_FAN);
}
return myModule;
}
@Override
public boolean isSuitableSdk(final Sdk sdk) {
return (sdk.getSdkType().equals(FanSdkType.getInstance()));
}
@Override
public Module commitModule(final Project project, final ModifiableModuleModel model) {
final Module m = super.commitModule(project, model);
final PodModel pod = getModulePod();
// hackery
if (TextUtil.isEmpty(pod.getOutDir())) {
pod.setOutDir("out/");
}
final String s = VirtualFileUtil.buildUrl(getContentEntryPath(), pod.getOutDir());
final File outFolder = new File(s);
outFolder.mkdirs();
pod.setOutDir(s);
final VirtualFile v = FanUtil.generateBuildScript(this.getContentEntryPath(), project, pod);
pod.setBuildScriptFile(v);
FanModuleSettings.getInstance(m).setBuildScript(v);
final List l = this.getSourcePaths();
l.clear();
l.addAll(pod.getSrcDirs());
l.addAll(pod.getResDirs());
return m;
}
@Override
public void setupRootModel(final ModifiableRootModel modifiableRootModel) throws ConfigurationException {
final FanIndex index = (FanIndex) modifiableRootModel.getProject().getComponent(FanIndex.COMPONENT_NAME);
final Module module = modifiableRootModel.getModule();
if (mySdk != null) {
modifiableRootModel.setSdk(mySdk);
//HACK. Otherwise for new Project first roots change event have wrong SDK!
// Value must be same as key, not clone!
ProjectJdksModel.getInstance(module.getProject()).getProjectJdks().put(mySdk, mySdk);
if (mySdk.getSdkType().equals(FanSdkType.getInstance())) {
final String s = VirtualFileUtil.buildUrl(getContentEntryPath(), PodModel.BUILD_FAN);
final VirtualFile v = VirtualFileUtil.refreshAndFindFileByLocalPath(s);
modulePod.setBuildScriptFile(v);
FanModuleSettings.getInstance(module).setBuildScript(v);
final PodModel tmpPodModel = PodFileParser.parse(modulePod.getBuildScriptFile(), mySdk);
if (tmpPodModel != null) {
modulePod.setName(tmpPodModel.getName());
modulePod.setDescription(tmpPodModel.getDescription());
modulePod.setVersion(tmpPodModel.getVersion());
modulePod.setDependencies(tmpPodModel.getDependencies());
modulePod.setSrcDirs(tmpPodModel.getSrcDirs());
modulePod.setDocApi(tmpPodModel.getDocApi());
modulePod.setDocSrc(tmpPodModel.getDocSrc());
modulePod.setOutDir(tmpPodModel.getOutDir());
modulePod.setIndexes(tmpPodModel.getIndexes());
modulePod.setMetas(tmpPodModel.getMetas());
modulePod.setResDirs(tmpPodModel.getResDirs());
clearModuleLibrary();
final List<String> dependencies = modulePod.getDependencies();
for (final String dependency : dependencies) {
addModuleLibrary(dependency, dependency);
}
}
}
} else {
modifiableRootModel.inheritSdk();
}
setupContentRoot(modifiableRootModel);
// Add pod dependencies as module libraries
final LibraryTable libraryTable = modifiableRootModel.getModuleLibraryTable();
for (final Pair<String, String> libInfo : myModuleLibraries) {
final String moduleLibraryPath = libInfo.first;
final String sourceLibraryPath = libInfo.second;
final File libFile = new File(moduleLibraryPath);
final Library library = libraryTable.createLibrary();
final Library.ModifiableModel modifiableModel = library.getModifiableModel();
modifiableModel.setName(libFile.getName());
modifiableModel.addRoot(moduleLibraryPath, OrderRootType.CLASSES);
if (sourceLibraryPath != null) {
modifiableModel.addRoot(sourceLibraryPath, OrderRootType.SOURCES);
}
modifiableModel.commit();
index.indexLibrary(library);
}
}
@Override
public ModuleType getModuleType() {
return FanModuleType.getInstance();
}
public String getContentEntryPath() {
return myContentRootPath;
}
public void setContentEntryPath(final String moduleRootPath) {
myContentRootPath = moduleRootPath;
}
public List<Pair<String, String>> getSourcePaths() {
return mySourcePaths;
}
public void addSourcePath(final Pair<String, String> sourcePathInfo) {
if (mySourcePaths == null) {
mySourcePaths = new ArrayList<Pair<String, String>>();
}
mySourcePaths.add(sourcePathInfo);
}
public void setSourcePaths(final List<Pair<String, String>> sourcePaths) {
mySourcePaths.clear();
mySourcePaths.addAll(sourcePaths);
}
@Nullable
public Sdk getSdk() {
return mySdk;
}
public void setSdk(final Sdk jdk) {
mySdk = jdk;
}
public PodModel getModulePod() {
return modulePod;
}
public void setModulePod(final PodModel modulePod) {
this.modulePod = modulePod;
}
public void addModuleLibrary(final String moduleLibraryPath, final String sourcePath) {
myModuleLibraries.add(Pair.create(moduleLibraryPath, sourcePath));
}
public void clearModuleLibrary() {
myModuleLibraries.clear();
}
private void setupContentRoot(final ModifiableRootModel rootModel) {
final String moduleRootPath = getContentEntryPath();
if (moduleRootPath != null) {
final LocalFileSystem lfs = LocalFileSystem.getInstance();
final VirtualFile moduleContentRoot = lfs.refreshAndFindFileByPath(FileUtil.toSystemIndependentName(moduleRootPath));
if (moduleContentRoot != null) {
final ContentEntry contentEntry = rootModel.addContentEntry(moduleContentRoot);
final List<Pair<String, String>> sourcePaths = getSourcePaths();
if (sourcePaths != null) {
for (final Pair<String, String> sourcePath : sourcePaths) {
final VirtualFile sourceRoot = lfs.refreshAndFindFileByPath(FileUtil.toSystemIndependentName(sourcePath.first));
if (sourceRoot != null) {
contentEntry.addSourceFolder(sourceRoot, false, sourcePath.second);
}
}
}
}
}
}
}