save project as template: custom file processing

This commit is contained in:
Dmitry Avdeev
2013-02-18 14:07:31 +04:00
parent 2ae7cd6d7b
commit f13a648058
12 changed files with 361 additions and 42 deletions
@@ -19,6 +19,7 @@ import com.intellij.CommonBundle;
import com.intellij.codeInspection.defaultFileTemplateUsage.FileHeaderChecker;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.util.projectWizard.ProjectTemplateFileProcessor;
import com.intellij.ide.util.projectWizard.ProjectTemplateParameterFactory;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -118,20 +119,7 @@ public class SaveProjectAsTemplateAction extends AnAction {
boolean replaceParameters,
final ProgressIndicator indicator) {
final Map<String, String> parameters = new HashMap<String, String>();
if (replaceParameters) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
ProjectTemplateParameterFactory[] extensions = Extensions.getExtensions(ProjectTemplateParameterFactory.EP_NAME);
for (ProjectTemplateParameterFactory extension : extensions) {
String value = extension.detectParameterValue(project);
if (value != null) {
parameters.put(value, extension.getParameterId());
}
}
}
});
}
final Map<String, String> parameters = computeParameters(project, replaceParameters);
indicator.setText("Saving project...");
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
@@ -180,41 +168,32 @@ public class SaveProjectAsTemplateAction extends AnAction {
: ModuleRootManager.getInstance(moduleToSave).getFileIndex();
final ZipOutputStream finalStream = stream;
final FileTemplate template = FileTemplateManager.getInstance().getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME);
final String templateText = template.getText();
final Pattern pattern = FileHeaderChecker.getTemplatePattern(template, project, new TIntObjectHashMap<String>());
index.iterateContent(new ContentIterator() {
@Override
public boolean processFile(final VirtualFile virtualFile) {
if (!virtualFile.isDirectory()) {
String name = virtualFile.getName();
indicator.setText2(name);
final String fileName = virtualFile.getName();
indicator.setText2(fileName);
try {
String relativePath = VfsUtilCore.getRelativePath(virtualFile, dir, '/');
if (relativePath == null) {
throw new RuntimeException("Can't find relative path for " + virtualFile);
}
boolean system = ".idea".equals(virtualFile.getParent().getName());
final boolean system = ".idea".equals(virtualFile.getParent().getName());
if (system) {
if (!name.equals("description.html") &&
!name.equals("misc.xml") &&
!name.equals("modules.xml") &&
!name.equals("workspace.xml")) {
if (!fileName.equals("description.html") &&
!fileName.equals("misc.xml") &&
!fileName.equals("modules.xml") &&
!fileName.equals("workspace.xml")) {
return true;
}
}
ZipUtil.addFileToZip(finalStream, new File(virtualFile.getPath()), dir.getName() + "/" + relativePath, null, null, new ZipUtil.FileContentProcessor() {
@Override
public InputStream getContent(File file) throws IOException {
public InputStream getContent(final File file) throws IOException {
if (virtualFile.getFileType().isBinary()) return STANDARD.getContent(file);
String s = VfsUtilCore.loadText(virtualFile);
String result = convertTemplates(s, pattern, templateText);
for (Map.Entry<String, String> entry : parameters.entrySet()) {
result = result.replace(entry.getKey(), "${" + entry.getValue() + "}");
}
String result = getEncodedContent(virtualFile, project, parameters);
return new ByteArrayInputStream(result.getBytes(TemplateModuleBuilder.UTF_8));
}
});
@@ -241,6 +220,39 @@ public class SaveProjectAsTemplateAction extends AnAction {
}
}
public static Map<String, String> computeParameters(final Project project, boolean replaceParameters) {
final Map<String, String> parameters = new HashMap<String, String>();
if (replaceParameters) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
ProjectTemplateParameterFactory[] extensions = Extensions.getExtensions(ProjectTemplateParameterFactory.EP_NAME);
for (ProjectTemplateParameterFactory extension : extensions) {
String value = extension.detectParameterValue(project);
if (value != null) {
parameters.put(value, extension.getParameterId());
}
}
}
});
}
return parameters;
}
public static String getEncodedContent(VirtualFile virtualFile,
Project project,
Map<String, String> parameters) throws IOException {
final FileTemplate template = FileTemplateManager.getInstance().getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME);
final String templateText = template.getText();
final Pattern pattern = FileHeaderChecker.getTemplatePattern(template, project, new TIntObjectHashMap<String>());
String text = VfsUtilCore.loadText(virtualFile);
String result = convertTemplates(text, pattern, templateText);
result = ProjectTemplateFileProcessor.encodeFile(result, virtualFile, project);
for (Map.Entry<String, String> entry : parameters.entrySet()) {
result = result.replace(entry.getKey(), "${" + entry.getValue() + "}");
}
return result;
}
private static VirtualFile getDirectoryToSave(Project project, @Nullable Module module) {
if (module == null) {
return project.getBaseDir();
@@ -0,0 +1,76 @@
/*
* Copyright 2000-2013 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 com.intellij.platform.templates;
import com.intellij.ide.util.projectWizard.ProjectTemplateComponent;
import com.intellij.ide.util.projectWizard.ProjectTemplateFileProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
/**
* @author Dmitry Avdeev
* Date: 2/15/13
*/
public class SystemFileProcessor extends ProjectTemplateFileProcessor {
@Nullable
@Override
protected String encodeFileText(String content, VirtualFile file, Project project) throws IOException {
final String fileName = file.getName();
if (file.getParent().getName().equals(".idea") && fileName.equals("workspace.xml")) {
ProjectTemplateComponent[] components = project.getComponents(ProjectTemplateComponent.class);
List<ProjectTemplateComponent> componentList = ContainerUtil.filter(components, new Condition<ProjectTemplateComponent>() {
@Override
public boolean value(ProjectTemplateComponent component) {
return fileName.equals(component.getStorageFile());
}
});
if (!componentList.isEmpty()) {
Element root = new Element("project");
for (final ProjectTemplateComponent component : componentList) {
final Element element = new Element("component");
root.addContent(element);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
((JDOMExternalizable)component).writeExternal(element);
}
catch (WriteExternalException ignore) {
LOG.error(ignore);
}
}
});
}
return JDOMUtil.writeElement(root);
}
}
return null;
}
private static final Logger LOG = Logger.getInstance(SystemFileProcessor.class);
}
@@ -154,7 +154,7 @@ public class TemplateModuleBuilder extends ModuleBuilder {
public Module createModule(@NotNull ModifiableModuleModel moduleModel)
throws InvalidDataException, IOException, ModuleWithNameAlreadyExists, JDOMException, ConfigurationException {
final String path = getContentEntryPath();
unzip(path, true);
unzip(null, path, true);
Module module = ImportImlMode.setUpLoader(getModuleFilePath()).createModule(moduleModel);
if (myProjectMode) {
moduleModel.renameModule(module, module.getProject().getName());
@@ -181,7 +181,7 @@ public class TemplateModuleBuilder extends ModuleBuilder {
return null;
}
private void unzip(String path, final boolean moduleMode) {
private void unzip(final String name, String path, final boolean moduleMode) {
File dir = new File(path);
ZipInputStream zipInputStream = null;
final WizardInputField basePackage = getBasePackageField();
@@ -202,7 +202,7 @@ public class TemplateModuleBuilder extends ModuleBuilder {
@Override
public byte[] processContent(byte[] content, String fileName) throws IOException {
FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(FileUtilRt.getExtension(fileName));
return fileType.isBinary() ? content : processTemplates(new String(content));
return fileType.isBinary() ? content : processTemplates(name, new String(content));
}
});
String iml = ContainerUtil.find(dir.list(), new Condition<String>() {
@@ -236,11 +236,12 @@ public class TemplateModuleBuilder extends ModuleBuilder {
return "/" + value.replace('.', '/') + "/";
}
private byte[] processTemplates(String s) throws IOException {
private byte[] processTemplates(String projectName, String s) throws IOException {
Properties properties = FileTemplateManager.getInstance().getDefaultProperties();
for (WizardInputField field : myAdditionalFields) {
properties.putAll(field.getValues());
}
properties.put(ProjectTemplateParameterFactory.IJ_PROJECT_NAME, projectName);
String merged = FileTemplateUtil.mergeTemplate(properties, s, true);
return merged.replace("\\$", "$").replace("\\#", "#").getBytes(UTF_8);
}
@@ -249,7 +250,7 @@ public class TemplateModuleBuilder extends ModuleBuilder {
@Override
public Project createProject(String name, final String path) {
myProjectMode = true;
unzip(path, false);
unzip(name, path, false);
return ApplicationManager.getApplication().runWriteAction(new NullableComputable<Project>() {
@Nullable
@Override
@@ -0,0 +1,46 @@
/*
* Copyright 2000-2013 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 com.intellij.ide.util.projectWizard;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
/**
* @author Dmitry Avdeev
* Date: 2/15/13
*/
public abstract class ProjectTemplateFileProcessor {
public static final ExtensionPointName<ProjectTemplateFileProcessor> EP_NAME = ExtensionPointName.create("com.intellij.projectTemplateFileProcessor");
/** Return null if it can't be processed */
@Nullable
protected abstract String encodeFileText(String content, VirtualFile file, Project project) throws IOException;
public static String encodeFile(String content, VirtualFile file, Project project) throws IOException {
ProjectTemplateFileProcessor[] processors = EP_NAME.getExtensions();
for (ProjectTemplateFileProcessor processor : processors) {
String text = processor.encodeFileText(content, file, project);
if (text != null) return text;
}
return VfsUtilCore.loadText(file);
}
}
@@ -18,16 +18,15 @@ package com.intellij.openapi.fileEditor.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.problems.WolfTheProblemSolver;
import com.intellij.psi.*;
@@ -152,8 +151,14 @@ public class PsiAwareFileEditorManagerImpl extends FileEditorManagerImpl {
private void doChange(final PsiTreeChangeEvent event) {
final PsiFile psiFile = event.getFile();
if (psiFile == null) return;
VirtualFile file = psiFile.getVirtualFile();
if (file == null) return;
FileEditor[] editors = getAllEditors(file);
if (editors.length == 0) return;
final VirtualFile currentFile = getCurrentFile();
if (currentFile != null && psiFile != null && Comparing.equal(psiFile.getVirtualFile(), currentFile)) {
if (currentFile != null && Comparing.equal(psiFile.getVirtualFile(), currentFile)) {
updateFileIcon(currentFile);
}
}
@@ -0,0 +1,25 @@
/*
* Copyright 2000-2013 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 com.intellij.ide.util.projectWizard;
/**
* @author Dmitry Avdeev
* Date: 2/15/13
*/
public interface ProjectTemplateComponent {
String getStorageFile();
}
@@ -20,6 +20,7 @@ import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.UISettingsListener;
import com.intellij.ide.util.projectWizard.ProjectTemplateComponent;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
@@ -93,7 +94,7 @@ import java.util.List;
* @author Eugene Belyaev
* @author Vladimir Kondratyev
*/
public class FileEditorManagerImpl extends FileEditorManagerEx implements ProjectComponent, JDOMExternalizable {
public class FileEditorManagerImpl extends FileEditorManagerEx implements ProjectComponent, JDOMExternalizable, ProjectTemplateComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl");
private static final Key<LocalFileSystem.WatchRequest> WATCH_REQUEST_KEY = Key.create("WATCH_REQUEST_KEY");
private static final Key<Boolean> DUMB_AWARE = Key.create("DUMB_AWARE");
@@ -251,6 +252,11 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
}
@Override
public String getStorageFile() {
return "workspace.xml";
}
private static class MyBorder implements Border {
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
@@ -1175,6 +1181,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
@Override
public FileEditor[] getAllEditors(@NotNull VirtualFile file) {
List<EditorWithProviderComposite> editorComposites = getEditorComposites(file);
if (editorComposites.isEmpty()) return EMPTY_EDITOR_ARRAY;
List<FileEditor> editors = new ArrayList<FileEditor>();
for (EditorWithProviderComposite composite : editorComposites) {
ContainerUtil.addAll(editors, composite.getEditors());
@@ -605,6 +605,9 @@
<extensionPoint name="projectTemplateParameterFactory"
interface="com.intellij.ide.util.projectWizard.ProjectTemplateParameterFactory"/>
<extensionPoint name="projectTemplateFileProcessor"
interface="com.intellij.ide.util.projectWizard.ProjectTemplateFileProcessor"/>
<extensionPoint name="facetType"
interface="com.intellij.facet.FacetType"/>
@@ -0,0 +1,66 @@
/*
* Copyright 2000-2013 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 org.jetbrains.idea.maven.utils;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.ide.util.projectWizard.ProjectTemplateFileProcessor;
import com.intellij.ide.util.projectWizard.ProjectTemplateParameterFactory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import java.io.IOException;
/**
* @author Dmitry Avdeev
* Date: 2/15/13
*/
public class MavenTemplateFileProcessor extends ProjectTemplateFileProcessor {
@Nullable
@Override
protected String encodeFileText(final String content, final VirtualFile file, final Project project) throws IOException {
if ("pom.xml".equals(file.getName())) {
return ApplicationManager.getApplication().runReadAction(new ThrowableComputable<String, IOException>() {
@Override
public String compute() throws IOException {
PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("pom.xml", XmlFileType.INSTANCE, content);
final MavenDomProjectModel model = MavenDomUtil.getMavenDomModel(psiFile, MavenDomProjectModel.class);
if (model == null) return null;
String text = psiFile.getText();
XmlElement element = model.getName().getXmlElement();
if (element instanceof XmlTag) {
text = ((XmlTag)element).getValue().getTextRange().replace(text, "${" + ProjectTemplateParameterFactory.IJ_PROJECT_NAME + "}");
}
element = model.getArtifactId().getXmlElement();
if (element instanceof XmlTag) {
text = ((XmlTag)element).getValue().getTextRange().replace(text, "${" + ProjectTemplateParameterFactory.IJ_PROJECT_NAME + "}");
}
return text;
}
});
}
return null;
}
}
@@ -65,6 +65,7 @@
<liveTemplateContext implementation="org.jetbrains.idea.maven.utils.MavenLiveTemplateContextType"/>
<defaultLiveTemplatesProvider implementation="org.jetbrains.idea.maven.utils.MavenLiveTemplatesProvider"/>
<projectTemplateFileProcessor implementation="org.jetbrains.idea.maven.utils.MavenTemplateFileProcessor"/>
<xml.elementDescriptorProvider implementation="org.jetbrains.idea.maven.dom.MavenDomElementDescriptorProvider"/>
<dom.fileDescription implementation="org.jetbrains.idea.maven.dom.MavenDomProjectModelDescription"/>
@@ -0,0 +1,76 @@
/*
* Copyright 2000-2013 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 org.jetbrains.idea.maven.utils;
import com.intellij.ide.util.projectWizard.ProjectTemplateParameterFactory;
import com.intellij.platform.templates.SaveProjectAsTemplateAction;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import java.util.Map;
/**
* @author Dmitry Avdeev
* Date: 2/15/13
*/
public class MavenTemplateFileProcessorTest extends LightPlatformCodeInsightFixtureTestCase {
private static final String TEXT =
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <groupId>com.springapp</groupId>\n" +
" <artifactId>springapp</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <version>1.0-SNAPSHOT</version>\n" +
" <name>SpringApp</name>\n" +
"</project>";
public MavenTemplateFileProcessorTest() {
IdeaTestCase.initPlatformPrefix();
}
public void testProcessor() throws Exception {
PsiFile file = myFixture.configureByText("pom.xml", TEXT);
String s = new MavenTemplateFileProcessor().encodeFileText(TEXT, file.getVirtualFile(), getProject());
assertEquals("<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <groupId>com.springapp</groupId>\n" +
" <artifactId>${IJ_PROJECT_NAME}</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <version>1.0-SNAPSHOT</version>\n" +
" <name>${IJ_PROJECT_NAME}</name>\n" +
"</project>", s);
}
public void testSaveAsTemplate() throws Exception {
PsiFile file = myFixture.configureByText("pom.xml", TEXT);
Map<String,String> map = SaveProjectAsTemplateAction.computeParameters(getProject(), true);
map.put("com.springapp", ProjectTemplateParameterFactory.IJ_BASE_PACKAGE);
String content = SaveProjectAsTemplateAction.getEncodedContent(file.getVirtualFile(), getProject(), map);
assertEquals("<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <groupId>${IJ_BASE_PACKAGE}</groupId>\n" +
" <artifactId>${IJ_PROJECT_NAME}</artifactId>\n" +
" <packaging>jar</packaging>\n" +
" <version>1.0-SNAPSHOT</version>\n" +
" <name>${IJ_PROJECT_NAME}</name>\n" +
"</project>", content);
}
}
@@ -302,6 +302,7 @@
<projectTemplatesFactory implementation="com.intellij.platform.templates.RemoteTemplatesFactory"/>
-->
<projectTemplatesFactory implementation="com.intellij.platform.templates.PlainModuleTemplatesFactory"/>
<projectTemplateFileProcessor implementation="com.intellij.platform.templates.SystemFileProcessor"/>
<applicationService serviceImplementation="com.intellij.ide.util.newProjectWizard.SelectTemplateSettings"/>