b2b3741d41b4c1e1c59e67481c7224133aa77b81
[idea/community.git] / plugins / ui-designer / src / com / intellij / uiDesigner / StringDescriptorManager.java
1 /*
2  * Copyright 2000-2009 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
17 package com.intellij.uiDesigner;
18
19 import com.intellij.lang.properties.IProperty;
20 import com.intellij.lang.properties.PropertiesUtil;
21 import com.intellij.lang.properties.psi.PropertiesFile;
22 import com.intellij.openapi.module.Module;
23 import com.intellij.openapi.module.ModuleServiceManager;
24 import com.intellij.openapi.roots.ModuleRootAdapter;
25 import com.intellij.openapi.util.Pair;
26 import com.intellij.openapi.roots.ModuleRootListener;
27 import com.intellij.openapi.roots.ModuleRootEvent;
28 import com.intellij.reference.SoftReference;
29 import com.intellij.uiDesigner.lw.StringDescriptor;
30 import com.intellij.uiDesigner.radComponents.RadComponent;
31 import com.intellij.uiDesigner.radComponents.RadRootContainer;
32 import com.intellij.util.messages.MessageBus;
33 import com.intellij.ProjectTopics;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
36
37 import java.util.HashMap;
38 import java.util.Locale;
39 import java.util.Map;
40
41 /**
42  * @author yole
43  */
44 public class StringDescriptorManager {
45   private final Module myModule;
46   private final Map<Pair<Locale, String>, SoftReference<PropertiesFile>> myPropertiesFileCache = new HashMap<Pair<Locale, String>, SoftReference<PropertiesFile>>();
47
48   public StringDescriptorManager(final Module module, MessageBus bus) {
49     myModule = module;
50     bus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
51       public void rootsChanged(final ModuleRootEvent event) {
52         synchronized(myPropertiesFileCache) {
53           myPropertiesFileCache.clear();
54         }
55       }
56     });
57   }
58
59   public static StringDescriptorManager getInstance(Module module) {
60     return ModuleServiceManager.getService(module, StringDescriptorManager.class);
61   }
62
63   @Nullable public String resolve(@NotNull RadComponent component, @Nullable StringDescriptor descriptor) {
64     RadRootContainer root = (RadRootContainer) FormEditingUtil.getRoot(component);
65     Locale locale = (root != null) ? root.getStringDescriptorLocale() : null;
66     return resolve(descriptor, locale);
67   }
68
69   @Nullable public String resolve(@Nullable StringDescriptor descriptor, @Nullable Locale locale) {
70     if (descriptor == null) {
71       return null;
72     }
73
74     if (descriptor.getValue() != null) {
75       return descriptor.getValue();
76     }
77
78     IProperty prop = resolveToProperty(descriptor, locale);
79     if (prop != null) {
80       final String value = prop.getUnescapedValue();
81       if (value != null) {
82         return value;
83       }
84     }
85     // We have to return surrogate string in case if propFile name is invalid or bundle doesn't have specified key
86     return "[" + descriptor.getKey() + " / " + descriptor.getBundleName() + "]";
87   }
88
89   public IProperty resolveToProperty(@NotNull StringDescriptor descriptor, @Nullable Locale locale) {
90     String propFileName = descriptor.getDottedBundleName();
91     Pair<Locale, String> cacheKey = new Pair<Locale, String>(locale, propFileName);
92     SoftReference<PropertiesFile> propertiesFileRef;
93     synchronized (myPropertiesFileCache) {
94       propertiesFileRef = myPropertiesFileCache.get(cacheKey);
95     }
96     PropertiesFile propertiesFile = (propertiesFileRef == null) ? null : propertiesFileRef.get();
97     if (propertiesFile == null || !propertiesFile.getContainingFile().isValid()) {
98       propertiesFile = PropertiesUtil.getPropertiesFile(propFileName, myModule, locale);
99       synchronized (myPropertiesFileCache) {
100         myPropertiesFileCache.put(cacheKey, new SoftReference<PropertiesFile>(propertiesFile));
101       }
102     }
103
104     if (propertiesFile != null) {
105       final IProperty propertyByKey = propertiesFile.findPropertyByKey(descriptor.getKey());
106       if (propertyByKey != null) {
107         return propertyByKey;
108       }
109     }
110     return null;
111   }
112 }