removed out.println() usages
[fedora-idea.git] / lang-impl / src / com / intellij / codeInsight / template / impl / TemplateSettings.java
blob5b670f098e39159311e0973dc9de4a4d690f25e2
1 package com.intellij.codeInsight.template.impl;
3 import com.intellij.codeInsight.CodeInsightBundle;
4 import com.intellij.codeInsight.template.Template;
5 import com.intellij.openapi.application.PathManager;
6 import com.intellij.openapi.application.ex.DecodeDefaultsUtil;
7 import com.intellij.openapi.components.*;
8 import com.intellij.openapi.diagnostic.Logger;
9 import com.intellij.openapi.extensions.Extensions;
10 import com.intellij.openapi.options.SchemeProcessor;
11 import com.intellij.openapi.options.SchemesManager;
12 import com.intellij.openapi.options.SchemesManagerFactory;
13 import com.intellij.openapi.util.DefaultJDOMExternalizer;
14 import com.intellij.openapi.util.InvalidDataException;
15 import com.intellij.openapi.util.JDOMUtil;
16 import com.intellij.openapi.util.WriteExternalException;
17 import org.jdom.Document;
18 import org.jdom.Element;
19 import org.jdom.JDOMException;
20 import org.jetbrains.annotations.NonNls;
21 import org.jetbrains.annotations.NotNull;
22 import org.jetbrains.annotations.Nullable;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.util.*;
30 @State(
31 name="TemplateSettings",
32 storages= {
33 @Storage(
34 id="other",
35 file = "$APP_CONFIG$/other.xml"
38 public class TemplateSettings implements PersistentStateComponent<Element>, ExportableComponent {
40 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.template.impl.TemplateSettings");
42 public @NonNls static final String USER_GROUP_NAME = "user";
43 private @NonNls static final String TEMPLATE_SET = "templateSet";
44 private @NonNls static final String GROUP = "group";
45 private @NonNls static final String TEMPLATE = "template";
47 private @NonNls static final String DELETED_TEMPLATES = "deleted_templates";
48 private List<String> myDeletedTemplates = new ArrayList<String>();
50 public static final char SPACE_CHAR = ' ';
51 public static final char TAB_CHAR = '\t';
52 public static final char ENTER_CHAR = '\n';
53 public static final char DEFAULT_CHAR = 'D';
55 private static final @NonNls String SPACE = "SPACE";
56 private static final @NonNls String TAB = "TAB";
57 private static final @NonNls String ENTER = "ENTER";
59 private static final @NonNls String NAME = "name";
60 private static final @NonNls String VALUE = "value";
61 private static final @NonNls String DESCRIPTION = "description";
62 private static final @NonNls String SHORTCUT = "shortcut";
64 private static final @NonNls String VARIABLE = "variable";
65 private static final @NonNls String EXPRESSION = "expression";
66 private static final @NonNls String DEFAULT_VALUE = "defaultValue";
67 private static final @NonNls String ALWAYS_STOP_AT = "alwaysStopAt";
69 private static final @NonNls String CONTEXT = "context";
70 private static final @NonNls String TO_REFORMAT = "toReformat";
71 private static final @NonNls String TO_SHORTEN_FQ_NAMES = "toShortenFQNames";
73 private static final @NonNls String DEFAULT_SHORTCUT = "defaultShortcut";
74 private static final @NonNls String DEACTIVATED = "deactivated";
76 @NonNls private static final String RESOURCE_BUNDLE = "resource-bundle";
77 @NonNls private static final String KEY = "key";
78 @NonNls private static final String ID = "id";
80 private static final @NonNls String TEMPLATES_CONFIG_FOLDER = "templates";
82 private final Map<String,Template> myTemplates = new LinkedHashMap<String,Template>();
83 private final Map<String,Template> myTemplatesById = new LinkedHashMap<String,Template>();
84 private final Map<String,TemplateImpl> myDefaultTemplates = new LinkedHashMap<String, TemplateImpl>();
86 private int myMaxKeyLength = 0;
87 private char myDefaultShortcutChar = TAB_CHAR;
88 private String myLastSelectedTemplateKey;
89 @NonNls
90 public static final String XML_EXTENSION = ".xml";
91 private final SchemesManager<TemplateGroup, TemplateGroup> mySchemesManager;
92 private final SchemeProcessor<TemplateGroup> myProcessor;
93 private static final String FILE_SPEC = "$ROOT_CONFIG$/templates";
95 public TemplateSettings(SchemesManagerFactory schemesManagerFactory) {
98 myProcessor = new SchemeProcessor<TemplateGroup>() {
99 public TemplateGroup readScheme(final Document schemeContent)
100 throws InvalidDataException, IOException, JDOMException {
101 return readTemplateFile(schemeContent, schemeContent.getRootElement().getAttributeValue("group"), false, false);
105 public boolean shouldBeSaved(final TemplateGroup template) {
106 for (TemplateImpl t : template.getTemplates()) {
107 if (!t.equals(myDefaultTemplates.get(t.getKey()))) {
108 return true;
111 return false;
114 public Document writeScheme(final TemplateGroup template) throws WriteExternalException {
115 Element templateSetElement = new Element(TEMPLATE_SET);
116 templateSetElement.setAttribute(GROUP, template.getName());
118 for (TemplateImpl t : template.getTemplates()) {
119 if (!t.equals(myDefaultTemplates.get(t.getKey()))) {
120 saveTemplate(t, templateSetElement);
124 return new Document(templateSetElement);
127 public void showReadErrorMessage(final Exception e, final String schemeName, final String filePath) {
128 LOG.warn(e);
131 public void showWriteErrorMessage(final Exception e, final String schemeName, final String filePath) {
132 LOG.warn(e);
135 public void initScheme(final TemplateGroup scheme) {
136 Collection<TemplateImpl> templates = scheme.getTemplates();
138 for (TemplateImpl template : templates) {
139 addTemplate(template);
144 mySchemesManager = schemesManagerFactory.createSchemesManager(FILE_SPEC, myProcessor, RoamingType.PER_USER);
146 loadTemplates();
149 @NotNull
150 public File[] getExportFiles() {
151 return new File[]{getTemplateDirectory(true),PathManager.getDefaultOptionsFile()};
154 @NotNull
155 public String getPresentableName() {
156 return CodeInsightBundle.message("templates.export.display.name");
159 public static TemplateSettings getInstance() {
160 return ServiceManager.getService(TemplateSettings.class);
163 public void loadState(Element parentNode) {
164 Element element = parentNode.getChild(DEFAULT_SHORTCUT);
165 if (element != null) {
166 String shortcut = element.getAttributeValue(SHORTCUT);
167 if (TAB.equals(shortcut)) {
168 myDefaultShortcutChar = TAB_CHAR;
169 } else if (ENTER.equals(shortcut)) {
170 myDefaultShortcutChar = ENTER_CHAR;
171 } else {
172 myDefaultShortcutChar = SPACE_CHAR;
176 Element deleted = parentNode.getChild(DELETED_TEMPLATES);
177 if (deleted != null) {
178 List children = deleted.getChildren();
179 for (final Object aChildren : children) {
180 Element child = (Element)aChildren;
181 myDeletedTemplates.add(child.getAttributeValue(NAME));
185 for (String name : myDeletedTemplates) {
186 Template toDelete = myTemplates.get(name);
187 if (toDelete != null) {
188 removeTemplate(toDelete);
192 //TODO lesya reload schemes
195 public Element getState() {
196 Element parentNode = new Element("TemplateSettings");
197 Element element = new Element(DEFAULT_SHORTCUT);
198 if (myDefaultShortcutChar == TAB_CHAR) {
199 element.setAttribute(SHORTCUT, TAB);
200 } else if (myDefaultShortcutChar == ENTER_CHAR) {
201 element.setAttribute(SHORTCUT, ENTER);
202 } else {
203 element.setAttribute(SHORTCUT, SPACE);
205 parentNode.addContent(element);
207 if (myDeletedTemplates.size() > 0) {
208 Element deleted = new Element(DELETED_TEMPLATES);
209 for (final String myDeletedTemplate : myDeletedTemplates) {
210 Element template = new Element(TEMPLATE);
211 template.setAttribute(NAME, myDeletedTemplate);
212 deleted.addContent(template);
215 parentNode.addContent(deleted);
217 return parentNode;
220 public String getLastSelectedTemplateKey() {
221 return myLastSelectedTemplateKey;
224 public void setLastSelectedTemplateKey(String key) {
225 myLastSelectedTemplateKey = key;
228 public TemplateImpl[] getTemplates() {
229 return myTemplates.values().toArray(new TemplateImpl[myTemplates.size()]);
232 public char getDefaultShortcutChar() {
233 return myDefaultShortcutChar;
236 public void setDefaultShortcutChar(char defaultShortcutChar) {
237 myDefaultShortcutChar = defaultShortcutChar;
240 public TemplateImpl getTemplate(@NonNls String key) {
241 return (TemplateImpl) myTemplates.get(key);
244 public Template getTemplateById(@NonNls String id) {
245 return myTemplatesById.get(id);
248 public int getMaxKeyLength() {
249 return myMaxKeyLength;
252 public void addTemplate(Template template) {
253 clearPreviouslyRegistered(template);
254 addTemplateImpl(template);
257 private void clearPreviouslyRegistered(final Template template) {
258 TemplateImpl existing = getTemplate(template.getKey());
259 if (existing != null) {
260 LOG.info("Template with key " + template.getKey() + " and id " + template.getId() + " already registered");
261 TemplateGroup group = mySchemesManager.findSchemeByName(existing.getGroupName());
262 if (group != null) {
263 group.removeTemplate(existing);
264 if (group.isEmpty()) {
265 mySchemesManager.removeScheme(group);
268 myTemplatesById.remove(template.getId());
269 myTemplates.remove(template.getKey());
273 private void addTemplateImpl(Template template) {
274 if (!myTemplates.containsKey(template.getKey()) && !myTemplatesById.containsKey(template.getId())) {
275 myTemplates.put(template.getKey(), template);
277 final String id = template.getId();
278 if (id != null) {
279 myTemplatesById.put(id, template);
281 myMaxKeyLength = Math.max(myMaxKeyLength, template.getKey().length());
283 myDeletedTemplates.remove(template.getKey());
287 public void removeTemplate(Template template) {
288 myTemplates.remove(template.getKey());
289 myTemplatesById.remove(template.getId());
291 TemplateImpl templImpl = (TemplateImpl)template;
292 String groupName = templImpl.getGroupName();
293 TemplateGroup group = mySchemesManager.findSchemeByName(groupName);
295 if (group != null) {
296 group.removeTemplate((TemplateImpl)template);
297 if (group.isEmpty()) {
298 mySchemesManager.removeScheme(group);
304 private TemplateImpl addTemplate(String key, String string, String group, String description, String shortcut, boolean isDefault,
305 final String id) {
306 TemplateImpl template = new TemplateImpl(key, string, group);
307 template.setId(id);
308 template.setDescription(description);
309 if (TAB.equals(shortcut)) {
310 template.setShortcutChar(TAB_CHAR);
311 } else if (ENTER.equals(shortcut)) {
312 template.setShortcutChar(ENTER_CHAR);
313 } else if (SPACE.equals(shortcut)) {
314 template.setShortcutChar(SPACE_CHAR);
315 } else {
316 template.setShortcutChar(DEFAULT_CHAR);
318 if (isDefault) {
319 myDefaultTemplates.put(key, template);
321 return template;
324 @Nullable
325 private static File getTemplateDirectory(boolean toCreate) {
326 String directoryPath = PathManager.getConfigPath() + File.separator + TEMPLATES_CONFIG_FOLDER;
327 File directory = new File(directoryPath);
328 if (!directory.exists()) {
329 if (!toCreate) {
330 return null;
332 if (!directory.mkdir()) {
333 if (LOG.isDebugEnabled()) {
334 LOG.debug("cannot create directory: " + directory.getAbsolutePath());
336 return null;
339 return directory;
342 private void loadTemplates() {
344 mySchemesManager.loadSchemes();
347 try {
348 for(DefaultLiveTemplatesProvider provider: Extensions.getExtensions(DefaultLiveTemplatesProvider.EP_NAME)) {
349 for (String defTemplate : provider.getDefaultLiveTemplateFiles()) {
350 String templateName = getDefaultTemplateName(defTemplate);
351 InputStream inputStream = DecodeDefaultsUtil.getDefaultsInputStream(provider, defTemplate);
352 if (inputStream != null) {
353 readDefTemplateFile(inputStream, templateName);
357 } catch (Exception e) {
358 LOG.error(e);
362 public static String getDefaultTemplateName(String defTemplate) {
363 return defTemplate.substring(defTemplate.lastIndexOf("/") + 1);
366 public void readDefTemplateFile(InputStream inputStream, String defGroupName) throws JDOMException, InvalidDataException, IOException {
367 readTemplateFile(JDOMUtil.loadDocument(inputStream), defGroupName, true, true);
370 @Nullable
371 public TemplateGroup readTemplateFile(Document document, @NonNls String defGroupName, boolean isDefault, boolean registerTemplate) throws InvalidDataException {
372 if (document == null) {
373 throw new InvalidDataException();
375 Element root = document.getRootElement();
376 if (root == null || !TEMPLATE_SET.equals(root.getName())) {
377 throw new InvalidDataException();
380 String groupName = root.getAttributeValue(GROUP);
381 if (groupName == null || groupName.length() == 0) groupName = defGroupName;
383 TemplateGroup result = new TemplateGroup(groupName);
385 Map<String, TemplateImpl> created = new LinkedHashMap<String, TemplateImpl>();
387 for (final Object o1 : root.getChildren(TEMPLATE)) {
388 Element element = (Element)o1;
390 String name = element.getAttributeValue(NAME);
391 String value = element.getAttributeValue(VALUE);
392 String description;
393 String resourceBundle = element.getAttributeValue(RESOURCE_BUNDLE);
394 String key = element.getAttributeValue(KEY);
395 String id = element.getAttributeValue(ID);
396 if (resourceBundle != null && key != null) {
397 ResourceBundle bundle = ResourceBundle.getBundle(resourceBundle);
398 description = bundle.getString(key);
400 else {
401 description = element.getAttributeValue(DESCRIPTION);
403 String shortcut = element.getAttributeValue(SHORTCUT);
404 if (isDefault && (myDeletedTemplates.contains(name) || myTemplates.containsKey(name))) continue;
405 TemplateImpl template = addTemplate(name, value, groupName, description, shortcut, isDefault, id);
406 template.setToReformat(Boolean.parseBoolean(element.getAttributeValue(TO_REFORMAT)));
407 template.setToShortenLongNames(Boolean.parseBoolean(element.getAttributeValue(TO_SHORTEN_FQ_NAMES)));
408 template.setDeactivated(Boolean.parseBoolean(element.getAttributeValue(DEACTIVATED)));
411 for (final Object o : element.getChildren(VARIABLE)) {
412 Element e = (Element)o;
413 String variableName = e.getAttributeValue(NAME);
414 String expression = e.getAttributeValue(EXPRESSION);
415 String defaultValue = e.getAttributeValue(DEFAULT_VALUE);
416 boolean isAlwaysStopAt = Boolean.parseBoolean(e.getAttributeValue(ALWAYS_STOP_AT));
417 template.addVariable(variableName, expression, defaultValue, isAlwaysStopAt);
420 Element context = element.getChild(CONTEXT);
421 if (context != null) {
422 DefaultJDOMExternalizer.readExternal(template.getTemplateContext(), context);
425 created.put(template.getKey(), template);
431 if (registerTemplate) {
432 TemplateGroup existingScheme = mySchemesManager.findSchemeByName(result.getName());
433 if (existingScheme != null) {
434 result = existingScheme;
438 for (TemplateImpl template : created.values()) {
439 if (registerTemplate) {
440 addTemplate(template);
443 result.addTemplate(template);
446 if (registerTemplate) {
447 TemplateGroup existingScheme = mySchemesManager.findSchemeByName(result.getName());
448 if (existingScheme == null && !result.isEmpty()) {
449 mySchemesManager.addNewScheme(result, false);
453 return result.isEmpty() ? null : result;
457 private static void saveTemplate(TemplateImpl template, Element templateSetElement) {
458 Element element = new Element(TEMPLATE);
459 final String id = template.getId();
460 if (id != null) {
461 element.setAttribute(ID, id);
463 element.setAttribute(NAME, template.getKey());
464 element.setAttribute(VALUE, template.getString());
465 if (template.getShortcutChar() == TAB_CHAR) {
466 element.setAttribute(SHORTCUT, TAB);
467 } else if (template.getShortcutChar() == ENTER_CHAR) {
468 element.setAttribute(SHORTCUT, ENTER);
469 } else if (template.getShortcutChar() == SPACE_CHAR) {
470 element.setAttribute(SHORTCUT, SPACE);
472 if (template.getDescription() != null) {
473 element.setAttribute(DESCRIPTION, template.getDescription());
475 element.setAttribute(TO_REFORMAT, Boolean.toString(template.isToReformat()));
476 element.setAttribute(TO_SHORTEN_FQ_NAMES, Boolean.toString(template.isToShortenLongNames()));
477 if (template.isDeactivated()) {
478 element.setAttribute(DEACTIVATED, Boolean.toString(true));
481 for (int i = 0; i < template.getVariableCount(); i++) {
482 Element variableElement = new Element(VARIABLE);
483 variableElement.setAttribute(NAME, template.getVariableNameAt(i));
484 variableElement.setAttribute(EXPRESSION, template.getExpressionStringAt(i));
485 variableElement.setAttribute(DEFAULT_VALUE, template.getDefaultValueStringAt(i));
486 variableElement.setAttribute(ALWAYS_STOP_AT, Boolean.toString(template.isAlwaysStopAt(i)));
487 element.addContent(variableElement);
490 try {
491 Element contextElement = new Element(CONTEXT);
492 DefaultJDOMExternalizer.writeExternal(template.getTemplateContext(), contextElement);
493 element.addContent(contextElement);
494 } catch (WriteExternalException e) {
496 templateSetElement.addContent(element);
499 public void setTemplates(List<TemplateGroup> newGroups) {
500 myTemplates.clear();
501 myTemplatesById.clear();
502 myDeletedTemplates.clear();
503 for (TemplateImpl template : myDefaultTemplates.values()) {
504 myDeletedTemplates.add(template.getKey());
506 mySchemesManager.clearAllSchemes();
507 myMaxKeyLength = 0;
508 for (TemplateGroup group : newGroups) {
509 if (!group.isEmpty()) {
510 mySchemesManager.addNewScheme(group, true);
511 for (TemplateImpl template : group.getTemplates()) {
512 addTemplate(template);
518 public SchemesManager<TemplateGroup,TemplateGroup> getSchemesManager() {
519 return mySchemesManager;
522 public List<TemplateGroup> getTemplateGroups() {
523 return mySchemesManager.getAllSchemes();