package org.mule.devkit.idea.module;
import com.intellij.ide.util.EditorHelper;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.xml.XmlElement;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
import org.jetbrains.idea.maven.dom.model.MavenDomModule;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import org.jetbrains.idea.maven.execution.MavenRunner;
import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
import org.jetbrains.idea.maven.execution.MavenRunnerSettings;
import org.jetbrains.idea.maven.model.MavenArchetype;
import org.jetbrains.idea.maven.model.MavenConstants;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.project.MavenProjectsManagerWatcher;
import org.jetbrains.idea.maven.utils.MavenLog;
import org.jetbrains.idea.maven.utils.MavenUtil;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
public class MuleModuleBuilderHelper {
private final MavenId myProjectId;
private final MavenProject myAggregatorProject;
private final MavenProject myParentProject;
private final boolean myInheritGroupId;
private final boolean myInheritVersion;
private final MavenArchetype myArchetype;
private final String myCommandName;
private final String myModuleName;
private final String myModulePackage;
public MuleModuleBuilderHelper(MavenId projectId,
MavenProject aggregatorProject,
MavenProject parentProject,
boolean inheritGroupId,
boolean inheritVersion,
MavenArchetype archetype,
String moduleName,
String modulePackage,
String commaneName) {
myProjectId = projectId;
myAggregatorProject = aggregatorProject;
myParentProject = parentProject;
myInheritGroupId = inheritGroupId;
myInheritVersion = inheritVersion;
myArchetype = archetype;
myCommandName = commaneName;
myModuleName = moduleName;
myModulePackage = modulePackage;
}
public void configure(final Project project, final VirtualFile root, final boolean isInteractive) {
PsiFile[] psiFiles = myAggregatorProject != null
? new PsiFile[]{getPsiFile(project, myAggregatorProject.getFile())}
: PsiFile.EMPTY_ARRAY;
final VirtualFile pom = new WriteCommandAction<VirtualFile>(project, myCommandName, psiFiles) {
@Override
protected void run(Result<VirtualFile> result) throws Throwable {
VirtualFile file;
try {
file = root.createChildData(this, MavenConstants.POM_XML);
MavenUtil.runOrApplyMavenProjectFileTemplate(project, file, myProjectId, null, isInteractive);
result.setResult(file);
} catch (IOException e) {
showError(project, e);
return;
}
updateProjectPom(project, file);
if (myAggregatorProject != null) {
MavenDomProjectModel model = MavenDomUtil.getMavenDomProjectModel(project, myAggregatorProject.getFile());
model.getPackaging().setStringValue("pom");
MavenDomModule module = model.getModules().addModule();
module.setValue(getPsiFile(project, file));
}
}
}.execute().getResultObject();
if (pom == null) {
return;
}
if (myAggregatorProject == null) {
MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
manager.addManagedFiles(Collections.singletonList(pom));
}
if (myArchetype == null) {
try {
VfsUtil.createDirectories(root.getPath() + "/src/main/java");
VfsUtil.createDirectories(root.getPath() + "/src/test/java");
} catch (IOException e) {
MavenLog.LOG.info(e);
}
}
// execute when current dialog is closed (e.g. Project Structure)
MavenUtil.invokeLater(project, ModalityState.NON_MODAL, new Runnable() {
public void run() {
if (!pom.isValid()) {
return;
}
EditorHelper.openInEditor(getPsiFile(project, pom));
if (myArchetype != null) {
generateFromArchetype(project, pom);
}
}
});
}
private void updateProjectPom(final Project project, final VirtualFile pom) {
if (myParentProject == null) {
return;
}
new WriteCommandAction.Simple(project, myCommandName) {
protected void run() throws Throwable {
MavenDomProjectModel model = MavenDomUtil.getMavenDomProjectModel(project, pom);
if (model == null) {
return;
}
MavenDomUtil.updateMavenParent(model, myParentProject);
if (myInheritGroupId) {
XmlElement el = model.getGroupId().getXmlElement();
if (el != null) {
el.delete();
}
}
if (myInheritVersion) {
XmlElement el = model.getVersion().getXmlElement();
if (el != null) {
el.delete();
}
}
CodeStyleManager.getInstance(project).reformat(getPsiFile(project, pom));
pom.putUserData(MavenProjectsManagerWatcher.FORCE_IMPORT_AND_RESOLVE_ON_REFRESH, Boolean.TRUE);
try {
Document doc = FileDocumentManager.getInstance().getDocument(pom);
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(doc);
FileDocumentManager.getInstance().saveDocument(doc);
} finally {
pom.putUserData(MavenProjectsManagerWatcher.FORCE_IMPORT_AND_RESOLVE_ON_REFRESH, null);
}
}
}.execute();
}
private PsiFile getPsiFile(Project project, VirtualFile pom) {
return PsiManager.getInstance(project).findFile(pom);
}
private void generateFromArchetype(final Project project, final VirtualFile pom) {
final File workingDir;
try {
workingDir = FileUtil.createTempDirectory("archetype", "tmp");
workingDir.deleteOnExit();
} catch (IOException e) {
showError(project, e);
return;
}
MavenRunnerParameters params = new MavenRunnerParameters(
false, workingDir.getPath(), Collections.singletonList("org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate"), null);
MavenRunner runner = MavenRunner.getInstance(project);
MavenRunnerSettings settings = runner.getState().clone();
Map<String, String> props = settings.getMavenProperties();
props.put("interactiveMode", "false");
props.put("archetypeGroupId", myArchetype.groupId);
props.put("archetypeArtifactId", myArchetype.artifactId);
props.put("archetypeVersion", myArchetype.version);
if (myArchetype.repository != null) {
props.put("archetypeRepository", myArchetype.repository);
}
props.put("groupId", myProjectId.getGroupId());
props.put("artifactId", myProjectId.getArtifactId());
props.put("version", myProjectId.getVersion());
props.put("muleModuleName", myModuleName);
props.put("muleModulePackage", myModulePackage);
runner.run(params, settings, new Runnable() {
public void run() {
copyGeneratedFiles(workingDir, pom, project);
}
});
}
private void copyGeneratedFiles(File workingDir, VirtualFile pom, Project project) {
try {
FileUtil.copyDir(new File(workingDir, myProjectId.getArtifactId()), new File(pom.getParent().getPath()));
} catch (IOException e) {
showError(project, e);
return;
}
FileUtil.delete(workingDir);
pom.refresh(false, false);
updateProjectPom(project, pom);
LocalFileSystem.getInstance().refreshWithoutFileWatcher(true);
}
private void showError(Project project, Throwable e) {
MavenUtil.showError(project, "Failed to create a Maven project", e);
}
}