bb8370159e360d10b3a19925c4012a2c9cc6c3ea
[idea/community.git] / plugins / ui-designer / src / com / intellij / uiDesigner / StringDescriptorManager.java
1 // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
3 package com.intellij.uiDesigner;
4
5 import com.intellij.ProjectTopics;
6 import com.intellij.lang.properties.IProperty;
7 import com.intellij.lang.properties.PropertiesUtilBase;
8 import com.intellij.lang.properties.psi.PropertiesFile;
9 import com.intellij.openapi.module.Module;
10 import com.intellij.openapi.module.ModuleServiceManager;
11 import com.intellij.openapi.roots.ModuleRootEvent;
12 import com.intellij.openapi.roots.ModuleRootListener;
13 import com.intellij.openapi.util.Pair;
14 import com.intellij.uiDesigner.lw.StringDescriptor;
15 import com.intellij.uiDesigner.radComponents.RadComponent;
16 import com.intellij.uiDesigner.radComponents.RadRootContainer;
17 import com.intellij.util.containers.ContainerUtil;
18 import com.intellij.util.messages.MessageBus;
19 import org.jetbrains.annotations.NotNull;
20 import org.jetbrains.annotations.Nullable;
21
22 import java.util.Locale;
23 import java.util.Map;
24
25 /**
26  * @author yole
27  */
28 public class StringDescriptorManager {
29   private Module myModule;
30   private final Map<Pair<Locale, String>, PropertiesFile> myPropertiesFileCache = ContainerUtil.createSoftValueMap();
31
32   public StringDescriptorManager(final Module module, MessageBus bus) {
33     myModule = module;
34     bus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
35       @Override
36       public void rootsChanged(@NotNull final ModuleRootEvent event) {
37         synchronized(myPropertiesFileCache) {
38           myPropertiesFileCache.clear();
39         }
40       }
41     });
42   }
43
44   public static StringDescriptorManager getInstance(Module module) {
45     StringDescriptorManager service = ModuleServiceManager.getService(module, StringDescriptorManager.class);
46     if (service != null) {
47       service.myModule = module;
48     }
49     return service;
50   }
51
52   @Nullable public String resolve(@NotNull RadComponent component, @Nullable StringDescriptor descriptor) {
53     RadRootContainer root = (RadRootContainer) FormEditingUtil.getRoot(component);
54     Locale locale = (root != null) ? root.getStringDescriptorLocale() : null;
55     return resolve(descriptor, locale);
56   }
57
58   @Nullable public String resolve(@Nullable StringDescriptor descriptor, @Nullable Locale locale) {
59     if (descriptor == null) {
60       return null;
61     }
62
63     if (descriptor.getValue() != null) {
64       return descriptor.getValue();
65     }
66
67     IProperty prop = resolveToProperty(descriptor, locale);
68     if (prop != null) {
69       final String value = prop.getUnescapedValue();
70       if (value != null) {
71         return value;
72       }
73     }
74     // We have to return surrogate string in case if propFile name is invalid or bundle doesn't have specified key
75     return "[" + descriptor.getKey() + " / " + descriptor.getBundleName() + "]";
76   }
77
78   public IProperty resolveToProperty(@NotNull StringDescriptor descriptor, @Nullable Locale locale) {
79     String propFileName = descriptor.getDottedBundleName();
80     Pair<Locale, String> cacheKey = Pair.create(locale, propFileName);
81     PropertiesFile propertiesFile;
82     synchronized (myPropertiesFileCache) {
83       propertiesFile = myPropertiesFileCache.get(cacheKey);
84     }
85     if (propertiesFile == null || !propertiesFile.getContainingFile().isValid()) {
86       propertiesFile = PropertiesUtilBase.getPropertiesFile(propFileName, myModule, locale);
87       synchronized (myPropertiesFileCache) {
88         myPropertiesFileCache.put(cacheKey, propertiesFile);
89       }
90     }
91
92     if (propertiesFile != null) {
93       final IProperty propertyByKey = propertiesFile.findPropertyByKey(descriptor.getKey());
94       if (propertyByKey != null) {
95         return propertyByKey;
96       }
97     }
98     return null;
99   }
100 }