/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java

https://bitbucket.org/nbargnesi/idea · Java · 747 lines · 617 code · 114 blank · 16 comment · 160 complexity · fd2bc16d9180c31049fbbe3864c1588c MD5 · raw file

  1. /*
  2. * Copyright 2000-2012 JetBrains s.r.o.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.intellij.codeInsight.template.impl;
  17. import com.intellij.AbstractBundle;
  18. import com.intellij.codeInsight.CodeInsightBundle;
  19. import com.intellij.codeInsight.template.Template;
  20. import com.intellij.openapi.application.PathManager;
  21. import com.intellij.openapi.application.ex.DecodeDefaultsUtil;
  22. import com.intellij.openapi.components.*;
  23. import com.intellij.openapi.diagnostic.Logger;
  24. import com.intellij.openapi.extensions.Extensions;
  25. import com.intellij.openapi.options.BaseSchemeProcessor;
  26. import com.intellij.openapi.options.SchemeProcessor;
  27. import com.intellij.openapi.options.SchemesManager;
  28. import com.intellij.openapi.options.SchemesManagerFactory;
  29. import com.intellij.openapi.util.InvalidDataException;
  30. import com.intellij.openapi.util.JDOMUtil;
  31. import com.intellij.openapi.util.WriteExternalException;
  32. import com.intellij.util.containers.MultiMap;
  33. import org.jdom.Document;
  34. import org.jdom.Element;
  35. import org.jdom.JDOMException;
  36. import org.jetbrains.annotations.NonNls;
  37. import org.jetbrains.annotations.NotNull;
  38. import org.jetbrains.annotations.Nullable;
  39. import java.io.File;
  40. import java.io.IOException;
  41. import java.io.InputStream;
  42. import java.util.*;
  43. @State(
  44. name="TemplateSettings",
  45. storages= {
  46. @Storage(
  47. file = StoragePathMacros.APP_CONFIG + "/other.xml"
  48. )}
  49. )
  50. public class TemplateSettings implements PersistentStateComponent<Element>, ExportableComponent {
  51. private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.template.impl.TemplateSettings");
  52. public @NonNls static final String USER_GROUP_NAME = "user";
  53. private @NonNls static final String TEMPLATE_SET = "templateSet";
  54. private @NonNls static final String GROUP = "group";
  55. private @NonNls static final String TEMPLATE = "template";
  56. private @NonNls static final String DELETED_TEMPLATES = "deleted_templates";
  57. private final List<TemplateKey> myDeletedTemplates = new ArrayList<TemplateKey>();
  58. public static final char SPACE_CHAR = ' ';
  59. public static final char TAB_CHAR = '\t';
  60. public static final char ENTER_CHAR = '\n';
  61. public static final char DEFAULT_CHAR = 'D';
  62. private static final @NonNls String SPACE = "SPACE";
  63. private static final @NonNls String TAB = "TAB";
  64. private static final @NonNls String ENTER = "ENTER";
  65. private static final @NonNls String NAME = "name";
  66. private static final @NonNls String VALUE = "value";
  67. private static final @NonNls String DESCRIPTION = "description";
  68. private static final @NonNls String SHORTCUT = "shortcut";
  69. private static final @NonNls String VARIABLE = "variable";
  70. private static final @NonNls String EXPRESSION = "expression";
  71. private static final @NonNls String DEFAULT_VALUE = "defaultValue";
  72. private static final @NonNls String ALWAYS_STOP_AT = "alwaysStopAt";
  73. private static final @NonNls String CONTEXT = "context";
  74. private static final @NonNls String TO_REFORMAT = "toReformat";
  75. private static final @NonNls String TO_SHORTEN_FQ_NAMES = "toShortenFQNames";
  76. private static final @NonNls String USE_STATIC_IMPORT = "useStaticImport";
  77. private static final @NonNls String DEFAULT_SHORTCUT = "defaultShortcut";
  78. private static final @NonNls String DEACTIVATED = "deactivated";
  79. @NonNls private static final String RESOURCE_BUNDLE = "resource-bundle";
  80. @NonNls private static final String KEY = "key";
  81. @NonNls private static final String ID = "id";
  82. private static final @NonNls String TEMPLATES_CONFIG_FOLDER = "templates";
  83. private final MultiMap<String,TemplateImpl> myTemplates = new MultiMap<String,TemplateImpl>() {
  84. @Override
  85. protected Map<String, Collection<TemplateImpl>> createMap() {
  86. return new LinkedHashMap<String, Collection<TemplateImpl>>();
  87. }
  88. };
  89. private final Map<String,Template> myTemplatesById = new LinkedHashMap<String,Template>();
  90. private final Map<TemplateKey,TemplateImpl> myDefaultTemplates = new LinkedHashMap<TemplateKey, TemplateImpl>();
  91. private int myMaxKeyLength = 0;
  92. private char myDefaultShortcutChar = TAB_CHAR;
  93. private final SchemesManager<TemplateGroup, TemplateGroup> mySchemesManager;
  94. private static final String FILE_SPEC = "$ROOT_CONFIG$/templates";
  95. public static class TemplateKey {
  96. private String groupName;
  97. private String key;
  98. @SuppressWarnings("UnusedDeclaration")
  99. public TemplateKey() {}
  100. private TemplateKey(String groupName, String key) {
  101. this.groupName = groupName;
  102. this.key = key;
  103. }
  104. public static TemplateKey keyOf(TemplateImpl template) {
  105. return new TemplateKey(template.getGroupName(), template.getKey());
  106. }
  107. public boolean equals(Object o) {
  108. if (this == o) return true;
  109. if (o == null || getClass() != o.getClass()) return false;
  110. TemplateKey that = (TemplateKey)o;
  111. if (groupName != null ? !groupName.equals(that.groupName) : that.groupName != null) return false;
  112. if (key != null ? !key.equals(that.key) : that.key != null) return false;
  113. return true;
  114. }
  115. public int hashCode() {
  116. int result = groupName != null ? groupName.hashCode() : 0;
  117. result = 31 * result + (key != null ? key.hashCode() : 0);
  118. return result;
  119. }
  120. public String getGroupName() {
  121. return groupName;
  122. }
  123. @SuppressWarnings("UnusedDeclaration")
  124. public void setGroupName(String groupName) {
  125. this.groupName = groupName;
  126. }
  127. public String getKey() {
  128. return key;
  129. }
  130. public void setKey(String key) {
  131. this.key = key;
  132. }
  133. }
  134. private TemplateKey myLastSelectedTemplate;
  135. public TemplateSettings(SchemesManagerFactory schemesManagerFactory) {
  136. SchemeProcessor<TemplateGroup> processor = new BaseSchemeProcessor<TemplateGroup>() {
  137. @Override
  138. @Nullable
  139. public TemplateGroup readScheme(final Document schemeContent)
  140. throws InvalidDataException, IOException, JDOMException {
  141. return readTemplateFile(schemeContent, schemeContent.getRootElement().getAttributeValue("group"), false, false,
  142. getClass().getClassLoader());
  143. }
  144. @Override
  145. public boolean shouldBeSaved(final TemplateGroup template) {
  146. for (TemplateImpl t : template.getElements()) {
  147. if (differsFromDefault(t)) {
  148. return true;
  149. }
  150. }
  151. return false;
  152. }
  153. @Override
  154. public Document writeScheme(final TemplateGroup template) throws WriteExternalException {
  155. Element templateSetElement = new Element(TEMPLATE_SET);
  156. templateSetElement.setAttribute(GROUP, template.getName());
  157. for (TemplateImpl t : template.getElements()) {
  158. if (differsFromDefault(t)) {
  159. saveTemplate(t, templateSetElement);
  160. }
  161. }
  162. return new Document(templateSetElement);
  163. }
  164. @Override
  165. public void initScheme(final TemplateGroup scheme) {
  166. Collection<TemplateImpl> templates = scheme.getElements();
  167. for (TemplateImpl template : templates) {
  168. addTemplateImpl(template);
  169. }
  170. }
  171. @Override
  172. public void onSchemeAdded(final TemplateGroup scheme) {
  173. for (TemplateImpl template : scheme.getElements()) {
  174. addTemplateImpl(template);
  175. }
  176. }
  177. @Override
  178. public void onSchemeDeleted(final TemplateGroup scheme) {
  179. for (TemplateImpl template : scheme.getElements()) {
  180. removeTemplate(template);
  181. }
  182. }
  183. };
  184. mySchemesManager = schemesManagerFactory.createSchemesManager(FILE_SPEC, processor, RoamingType.PER_USER);
  185. loadTemplates();
  186. }
  187. private boolean differsFromDefault(TemplateImpl t) {
  188. TemplateImpl def = myDefaultTemplates.get(TemplateKey.keyOf(t));
  189. if (def == null) return true;
  190. return !t.equals(def) || !t.contextsEqual(def);
  191. }
  192. @Override
  193. @NotNull
  194. public File[] getExportFiles() {
  195. File exportableSettingsFile =
  196. new File(PathManager.getOptionsPath() + File.separator + ExportableTemplateSettings.EXPORTABLE_SETTINGS_FILE);
  197. return new File[]{getTemplateDirectory(true), exportableSettingsFile };
  198. }
  199. @Override
  200. @NotNull
  201. public String getPresentableName() {
  202. return CodeInsightBundle.message("templates.export.display.name");
  203. }
  204. public static TemplateSettings getInstance() {
  205. return ServiceManager.getService(TemplateSettings.class);
  206. }
  207. @Override
  208. public void loadState(Element parentNode) {
  209. Element element = parentNode.getChild(DEFAULT_SHORTCUT);
  210. if (element != null) {
  211. String shortcut = element.getAttributeValue(SHORTCUT);
  212. if (TAB.equals(shortcut)) {
  213. myDefaultShortcutChar = TAB_CHAR;
  214. } else if (ENTER.equals(shortcut)) {
  215. myDefaultShortcutChar = ENTER_CHAR;
  216. } else {
  217. myDefaultShortcutChar = SPACE_CHAR;
  218. }
  219. }
  220. ExportableTemplateSettings exportableSettings = ServiceManager.getService(ExportableTemplateSettings.class);
  221. assert exportableSettings != null : "Can't find required ExportablTemplateSettings service.";
  222. exportableSettings.setParentSettings(this);
  223. if (exportableSettings.isLoaded()) {
  224. myDeletedTemplates.addAll(exportableSettings.getDeletedKeys());
  225. }
  226. else {
  227. Element deleted = parentNode.getChild(DELETED_TEMPLATES);
  228. if (deleted != null) {
  229. List children = deleted.getChildren();
  230. for (final Object aChildren : children) {
  231. Element child = (Element)aChildren;
  232. myDeletedTemplates.add(new TemplateKey(child.getAttributeValue(GROUP), child.getAttributeValue(NAME)));
  233. }
  234. }
  235. }
  236. for (TemplateKey templateKey : myDeletedTemplates) {
  237. if (templateKey.groupName == null) {
  238. final Collection<TemplateImpl> templates = new ArrayList<TemplateImpl>(myTemplates.get(templateKey.key));
  239. for (TemplateImpl template : templates) {
  240. removeTemplate(template);
  241. }
  242. }
  243. else {
  244. final TemplateImpl toDelete = getTemplate(templateKey.key, templateKey.groupName);
  245. if (toDelete != null) {
  246. removeTemplate(toDelete);
  247. }
  248. }
  249. }
  250. //TODO lesya reload schemes
  251. }
  252. @Override
  253. public Element getState() {
  254. Element parentNode = new Element("TemplateSettings");
  255. Element element = new Element(DEFAULT_SHORTCUT);
  256. if (myDefaultShortcutChar == TAB_CHAR) {
  257. element.setAttribute(SHORTCUT, TAB);
  258. } else if (myDefaultShortcutChar == ENTER_CHAR) {
  259. element.setAttribute(SHORTCUT, ENTER);
  260. } else {
  261. element.setAttribute(SHORTCUT, SPACE);
  262. }
  263. parentNode.addContent(element);
  264. return parentNode;
  265. }
  266. @Nullable
  267. public String getLastSelectedTemplateKey() {
  268. return myLastSelectedTemplate != null ? myLastSelectedTemplate.key : null;
  269. }
  270. @Nullable
  271. public String getLastSelectedTemplateGroup() {
  272. return myLastSelectedTemplate != null ? myLastSelectedTemplate.groupName : null;
  273. }
  274. public void setLastSelectedTemplate(@Nullable String group, @Nullable String key) {
  275. myLastSelectedTemplate = group == null ? null : new TemplateKey(group, key);
  276. }
  277. public TemplateImpl[] getTemplates() {
  278. final Collection<? extends TemplateImpl> all = myTemplates.values();
  279. return all.toArray(new TemplateImpl[all.size()]);
  280. }
  281. public char getDefaultShortcutChar() {
  282. return myDefaultShortcutChar;
  283. }
  284. public void setDefaultShortcutChar(char defaultShortcutChar) {
  285. myDefaultShortcutChar = defaultShortcutChar;
  286. }
  287. public Collection<TemplateImpl> getTemplates(@NonNls String key) {
  288. return myTemplates.get(key);
  289. }
  290. @Nullable
  291. public TemplateImpl getTemplate(@NonNls String key, String group) {
  292. final Collection<TemplateImpl> templates = myTemplates.get(key);
  293. for (TemplateImpl template : templates) {
  294. if (template.getGroupName().equals(group)) {
  295. return template;
  296. }
  297. }
  298. return null;
  299. }
  300. public Template getTemplateById(@NonNls String id) {
  301. return myTemplatesById.get(id);
  302. }
  303. public int getMaxKeyLength() {
  304. return myMaxKeyLength;
  305. }
  306. public void addTemplate(Template template) {
  307. clearPreviouslyRegistered(template);
  308. addTemplateImpl(template);
  309. TemplateImpl templateImpl = (TemplateImpl)template;
  310. String groupName = templateImpl.getGroupName();
  311. TemplateGroup group = mySchemesManager.findSchemeByName(groupName);
  312. if (group == null) {
  313. group = new TemplateGroup(groupName);
  314. mySchemesManager.addNewScheme(group, true);
  315. }
  316. group.addElement(templateImpl);
  317. }
  318. private void clearPreviouslyRegistered(final Template template) {
  319. TemplateImpl existing = getTemplate(template.getKey(), ((TemplateImpl) template).getGroupName());
  320. if (existing != null) {
  321. LOG.info("Template with key " + template.getKey() + " and id " + template.getId() + " already registered");
  322. TemplateGroup group = mySchemesManager.findSchemeByName(existing.getGroupName());
  323. if (group != null) {
  324. group.removeElement(existing);
  325. if (group.isEmpty()) {
  326. mySchemesManager.removeScheme(group);
  327. }
  328. }
  329. myTemplates.removeValue(template.getKey(), existing);
  330. }
  331. }
  332. private void addTemplateImpl(Template template) {
  333. final TemplateImpl templateImpl = (TemplateImpl)template;
  334. if (getTemplate(templateImpl.getKey(), templateImpl.getGroupName()) == null) {
  335. myTemplates.putValue(template.getKey(), templateImpl);
  336. }
  337. myMaxKeyLength = Math.max(myMaxKeyLength, template.getKey().length());
  338. myDeletedTemplates.remove(TemplateKey.keyOf((TemplateImpl)template));
  339. }
  340. private void addTemplateById(Template template) {
  341. if (!myTemplatesById.containsKey(template.getId())) {
  342. final String id = template.getId();
  343. if (id != null) {
  344. myTemplatesById.put(id, template);
  345. }
  346. }
  347. }
  348. public void removeTemplate(Template template) {
  349. myTemplates.removeValue(template.getKey(), (TemplateImpl )template);
  350. TemplateImpl templateImpl = (TemplateImpl)template;
  351. String groupName = templateImpl.getGroupName();
  352. TemplateGroup group = mySchemesManager.findSchemeByName(groupName);
  353. if (group != null) {
  354. group.removeElement((TemplateImpl)template);
  355. if (group.isEmpty()) {
  356. mySchemesManager.removeScheme(group);
  357. }
  358. }
  359. }
  360. private TemplateImpl addTemplate(String key, String string, String group, String description, String shortcut, boolean isDefault,
  361. final String id) {
  362. TemplateImpl template = new TemplateImpl(key, string, group);
  363. template.setId(id);
  364. template.setDescription(description);
  365. if (TAB.equals(shortcut)) {
  366. template.setShortcutChar(TAB_CHAR);
  367. } else if (ENTER.equals(shortcut)) {
  368. template.setShortcutChar(ENTER_CHAR);
  369. } else if (SPACE.equals(shortcut)) {
  370. template.setShortcutChar(SPACE_CHAR);
  371. } else {
  372. template.setShortcutChar(DEFAULT_CHAR);
  373. }
  374. if (isDefault) {
  375. myDefaultTemplates.put(TemplateKey.keyOf(template), template);
  376. }
  377. return template;
  378. }
  379. @Nullable
  380. private static File getTemplateDirectory(boolean toCreate) {
  381. String directoryPath = PathManager.getConfigPath() + File.separator + TEMPLATES_CONFIG_FOLDER;
  382. File directory = new File(directoryPath);
  383. if (!directory.exists()) {
  384. if (!toCreate) {
  385. return null;
  386. }
  387. if (!directory.mkdir()) {
  388. if (LOG.isDebugEnabled()) {
  389. LOG.debug("cannot create directory: " + directory.getAbsolutePath());
  390. }
  391. return null;
  392. }
  393. }
  394. return directory;
  395. }
  396. private void loadTemplates() {
  397. Collection<TemplateGroup> loaded = mySchemesManager.loadSchemes();
  398. for (TemplateGroup group : loaded) {
  399. Collection<TemplateImpl> templates = group.getElements();
  400. for (TemplateImpl template : templates) {
  401. addTemplateImpl(template);
  402. }
  403. }
  404. loadDefaultLiveTemplates();
  405. }
  406. private void loadDefaultLiveTemplates() {
  407. try {
  408. for(DefaultLiveTemplatesProvider provider: Extensions.getExtensions(DefaultLiveTemplatesProvider.EP_NAME)) {
  409. for (String defTemplate : provider.getDefaultLiveTemplateFiles()) {
  410. readDefTemplate(provider, defTemplate, true);
  411. }
  412. try {
  413. String[] hidden = provider.getHiddenLiveTemplateFiles();
  414. if (hidden != null) {
  415. for (String s : hidden) {
  416. readDefTemplate(provider, s, false);
  417. }
  418. }
  419. }
  420. catch (AbstractMethodError ignore) {
  421. }
  422. }
  423. } catch (Exception e) {
  424. LOG.error(e);
  425. }
  426. }
  427. private void readDefTemplate(DefaultLiveTemplatesProvider provider, String defTemplate, boolean registerTemplate)
  428. throws JDOMException, InvalidDataException, IOException {
  429. String templateName = getDefaultTemplateName(defTemplate);
  430. InputStream inputStream = DecodeDefaultsUtil.getDefaultsInputStream(provider, defTemplate);
  431. if (inputStream != null) {
  432. TemplateGroup group =
  433. readTemplateFile(JDOMUtil.loadDocument(inputStream), templateName, true, registerTemplate, provider.getClass().getClassLoader());
  434. if (group != null && group.getReplace() != null) {
  435. Collection<TemplateImpl> templates = myTemplates.get(group.getReplace());
  436. for (TemplateImpl template : templates) {
  437. removeTemplate(template);
  438. }
  439. }
  440. }
  441. }
  442. private static String getDefaultTemplateName(String defTemplate) {
  443. return defTemplate.substring(defTemplate.lastIndexOf("/") + 1);
  444. }
  445. @Nullable
  446. private TemplateGroup readTemplateFile(Document document, @NonNls String defGroupName, boolean isDefault, boolean registerTemplate, ClassLoader classLoader) throws InvalidDataException {
  447. if (document == null) {
  448. throw new InvalidDataException();
  449. }
  450. Element root = document.getRootElement();
  451. if (root == null || !TEMPLATE_SET.equals(root.getName())) {
  452. throw new InvalidDataException();
  453. }
  454. String groupName = root.getAttributeValue(GROUP);
  455. if (groupName == null || groupName.length() == 0) groupName = defGroupName;
  456. TemplateGroup result = new TemplateGroup(groupName, root.getAttributeValue("REPLACE"));
  457. Map<String, TemplateImpl> created = new LinkedHashMap<String, TemplateImpl>();
  458. for (final Object o1 : root.getChildren(TEMPLATE)) {
  459. Element element = (Element)o1;
  460. TemplateImpl template = readTemplateFromElement(isDefault, groupName, element, classLoader);
  461. boolean defaultTemplateModified = isDefault && (myDeletedTemplates.contains(TemplateKey.keyOf(template)) ||
  462. myTemplatesById.containsKey(template.getId()) ||
  463. getTemplate(template.getKey(), template.getGroupName()) != null);
  464. if(!defaultTemplateModified) {
  465. created.put(template.getKey(), template);
  466. }
  467. }
  468. if (registerTemplate) {
  469. TemplateGroup existingScheme = mySchemesManager.findSchemeByName(result.getName());
  470. if (existingScheme != null) {
  471. result = existingScheme;
  472. }
  473. }
  474. for (TemplateImpl template : created.values()) {
  475. if (registerTemplate) {
  476. clearPreviouslyRegistered(template);
  477. addTemplateImpl(template);
  478. }
  479. addTemplateById(template);
  480. result.addElement(template);
  481. }
  482. if (registerTemplate) {
  483. TemplateGroup existingScheme = mySchemesManager.findSchemeByName(result.getName());
  484. if (existingScheme == null && !result.isEmpty()) {
  485. mySchemesManager.addNewScheme(result, false);
  486. }
  487. }
  488. return result.isEmpty() ? null : result;
  489. }
  490. private TemplateImpl readTemplateFromElement(final boolean isDefault,
  491. final String groupName,
  492. final Element element,
  493. ClassLoader classLoader) throws InvalidDataException {
  494. String name = element.getAttributeValue(NAME);
  495. String value = element.getAttributeValue(VALUE);
  496. String description;
  497. String resourceBundle = element.getAttributeValue(RESOURCE_BUNDLE);
  498. String key = element.getAttributeValue(KEY);
  499. String id = element.getAttributeValue(ID);
  500. if (resourceBundle != null && key != null) {
  501. if (classLoader == null) {
  502. classLoader = getClass().getClassLoader();
  503. }
  504. ResourceBundle bundle = AbstractBundle.getResourceBundle(resourceBundle, classLoader);
  505. description = bundle.getString(key);
  506. }
  507. else {
  508. description = element.getAttributeValue(DESCRIPTION);
  509. }
  510. String shortcut = element.getAttributeValue(SHORTCUT);
  511. TemplateImpl template = addTemplate(name, value, groupName, description, shortcut, isDefault, id);
  512. template.setToReformat(Boolean.parseBoolean(element.getAttributeValue(TO_REFORMAT)));
  513. template.setToShortenLongNames(Boolean.parseBoolean(element.getAttributeValue(TO_SHORTEN_FQ_NAMES)));
  514. template.setDeactivated(Boolean.parseBoolean(element.getAttributeValue(DEACTIVATED)));
  515. String useStaticImport = element.getAttributeValue(USE_STATIC_IMPORT);
  516. if (useStaticImport != null) {
  517. template.setValue(TemplateImpl.Property.USE_STATIC_IMPORT_IF_POSSIBLE, Boolean.parseBoolean(useStaticImport));
  518. }
  519. for (final Object o : element.getChildren(VARIABLE)) {
  520. Element e = (Element)o;
  521. String variableName = e.getAttributeValue(NAME);
  522. String expression = e.getAttributeValue(EXPRESSION);
  523. String defaultValue = e.getAttributeValue(DEFAULT_VALUE);
  524. boolean isAlwaysStopAt = Boolean.parseBoolean(e.getAttributeValue(ALWAYS_STOP_AT));
  525. template.addVariable(variableName, expression, defaultValue, isAlwaysStopAt);
  526. }
  527. Element context = element.getChild(CONTEXT);
  528. if (context != null) {
  529. template.getTemplateContext().readExternal(context);
  530. }
  531. return template;
  532. }
  533. private static void saveTemplate(TemplateImpl template, Element templateSetElement) {
  534. Element element = new Element(TEMPLATE);
  535. final String id = template.getId();
  536. if (id != null) {
  537. element.setAttribute(ID, id);
  538. }
  539. element.setAttribute(NAME, template.getKey());
  540. element.setAttribute(VALUE, template.getString());
  541. if (template.getShortcutChar() == TAB_CHAR) {
  542. element.setAttribute(SHORTCUT, TAB);
  543. } else if (template.getShortcutChar() == ENTER_CHAR) {
  544. element.setAttribute(SHORTCUT, ENTER);
  545. } else if (template.getShortcutChar() == SPACE_CHAR) {
  546. element.setAttribute(SHORTCUT, SPACE);
  547. }
  548. if (template.getDescription() != null) {
  549. element.setAttribute(DESCRIPTION, template.getDescription());
  550. }
  551. element.setAttribute(TO_REFORMAT, Boolean.toString(template.isToReformat()));
  552. element.setAttribute(TO_SHORTEN_FQ_NAMES, Boolean.toString(template.isToShortenLongNames()));
  553. if (template.getValue(Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE)
  554. != Template.getDefaultValue(Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE))
  555. {
  556. element.setAttribute(USE_STATIC_IMPORT, Boolean.toString(template.getValue(Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE)));
  557. }
  558. if (template.isDeactivated()) {
  559. element.setAttribute(DEACTIVATED, Boolean.toString(true));
  560. }
  561. for (int i = 0; i < template.getVariableCount(); i++) {
  562. Element variableElement = new Element(VARIABLE);
  563. variableElement.setAttribute(NAME, template.getVariableNameAt(i));
  564. variableElement.setAttribute(EXPRESSION, template.getExpressionStringAt(i));
  565. variableElement.setAttribute(DEFAULT_VALUE, template.getDefaultValueStringAt(i));
  566. variableElement.setAttribute(ALWAYS_STOP_AT, Boolean.toString(template.isAlwaysStopAt(i)));
  567. element.addContent(variableElement);
  568. }
  569. try {
  570. Element contextElement = new Element(CONTEXT);
  571. template.getTemplateContext().writeExternal(contextElement);
  572. element.addContent(contextElement);
  573. } catch (WriteExternalException ignore) {
  574. }
  575. templateSetElement.addContent(element);
  576. }
  577. public void setTemplates(List<TemplateGroup> newGroups) {
  578. myTemplates.clear();
  579. myDeletedTemplates.clear();
  580. for (TemplateImpl template : myDefaultTemplates.values()) {
  581. myDeletedTemplates.add(TemplateKey.keyOf(template));
  582. }
  583. mySchemesManager.clearAllSchemes();
  584. myMaxKeyLength = 0;
  585. for (TemplateGroup group : newGroups) {
  586. if (!group.isEmpty()) {
  587. mySchemesManager.addNewScheme(group, true);
  588. for (TemplateImpl template : group.getElements()) {
  589. clearPreviouslyRegistered(template);
  590. addTemplateImpl(template);
  591. }
  592. }
  593. }
  594. }
  595. public SchemesManager<TemplateGroup,TemplateGroup> getSchemesManager() {
  596. return mySchemesManager;
  597. }
  598. public List<TemplateGroup> getTemplateGroups() {
  599. return mySchemesManager.getAllSchemes();
  600. }
  601. public List<TemplateImpl> collectMatchingCandidates(String key, Character shortcutChar, boolean hasArgument) {
  602. final Collection<TemplateImpl> templates = getTemplates(key);
  603. List<TemplateImpl> candidates = new ArrayList<TemplateImpl>();
  604. for (TemplateImpl template : templates) {
  605. if (template.isDeactivated()) {
  606. continue;
  607. }
  608. if (shortcutChar != null && getShortcutChar(template) != shortcutChar) {
  609. continue;
  610. }
  611. if (template.isSelectionTemplate()) {
  612. continue;
  613. }
  614. if (hasArgument && !template.hasArgument()) {
  615. continue;
  616. }
  617. candidates.add(template);
  618. }
  619. return candidates;
  620. }
  621. public char getShortcutChar(TemplateImpl template) {
  622. char c = template.getShortcutChar();
  623. if (c == DEFAULT_CHAR) {
  624. return getDefaultShortcutChar();
  625. }
  626. else {
  627. return c;
  628. }
  629. }
  630. public List<TemplateKey> getDeletedTemplates() {
  631. return myDeletedTemplates;
  632. }
  633. }