diff options
Diffstat (limited to 'plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java')
-rw-r--r-- | plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java new file mode 100644 index 000000000000..a01c123f8763 --- /dev/null +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -0,0 +1,256 @@ +/* + * Copyright 2000-2014 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.lang.properties; + +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.*; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NullableComputable; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; + +/** + * @author Dmitry Batkovich + */ +@State( + name = "ResourceBundleManager", + storages = { + @Storage(file = StoragePathMacros.PROJECT_FILE), + @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/resourceBundles.xml", scheme = StorageScheme.DIRECTORY_BASED) + }) +public class ResourceBundleManager implements PersistentStateComponent<ResourceBundleManagerState> { + private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class); + private final static Locale DEFAULT_LOCALE = new Locale("", "", ""); + + private ResourceBundleManagerState myState = new ResourceBundleManagerState(); + + public ResourceBundleManager(final PsiManager manager) { + manager.addPsiTreeChangeListener(new PsiTreeChangeAdapter() { + @Override + public void childMoved(@NotNull PsiTreeChangeEvent event) { + final PsiElement child = event.getChild(); + if (!(child instanceof PsiFile)) { + return; + } + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile((PsiFile)child); + if (propertiesFile == null) { + return; + } + final String oldParentUrl = getUrl(event.getOldParent()); + final String newParentUrl = getUrl(event.getNewParent()); + if (oldParentUrl == null || newParentUrl == null) { + return; + } + final String newUrl = propertiesFile.getVirtualFile().getUrl(); + final String oldUrl = oldParentUrl + newUrl.substring(newParentUrl.length()); + if (myState.getDissociatedFiles().remove(oldUrl)) { + myState.getDissociatedFiles().add(newUrl); + } + + for (CustomResourceBundleState customResourceBundleState : myState.getCustomResourceBundles()) { + if (customResourceBundleState.getFileUrls().remove(oldUrl)) { + customResourceBundleState.getFileUrls().add(newUrl); + break; + } + } + } + + @Nullable + private String getUrl(PsiElement element) { + return !(element instanceof PsiDirectory) ? null : ((PsiDirectory)element).getVirtualFile().getUrl(); + } + + @Override + public void childReplaced(@NotNull PsiTreeChangeEvent event) { + super.childReplaced(event); + } + + @Override + public void beforeChildMovement(@NotNull PsiTreeChangeEvent event) { + super.beforeChildMovement(event); + } + + @Override + public void propertyChanged(@NotNull PsiTreeChangeEvent event) { + super.propertyChanged(event); + } + + @Override + public void childRemoved(@NotNull PsiTreeChangeEvent event) { + final PsiElement child = event.getChild(); + if (!(child instanceof PsiFile)) { + return; + } + PropertiesFile file = PropertiesImplUtil.getPropertiesFile((PsiFile)child); + if (file == null) { + return; + } + final VirtualFile virtualFile = file.getVirtualFile(); + final String url = virtualFile.getUrl(); + myState.getDissociatedFiles().remove(url); + for (CustomResourceBundleState customResourceBundleState : myState.getCustomResourceBundles()) { + if (customResourceBundleState.getFileUrls().remove(url)) { + if (customResourceBundleState.getFileUrls().size() < 2) { + myState.getCustomResourceBundles().remove(customResourceBundleState); + } + break; + } + } + } + }); + } + + public static ResourceBundleManager getInstance(final Project project) { + return ServiceManager.getService(project, ResourceBundleManager.class); + } + + @Nullable + public String getFullName(final @NotNull PropertiesFile propertiesFile) { + return ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() { + public String compute() { + final PsiDirectory directory = propertiesFile.getParent(); + final String packageQualifiedName = PropertiesUtil.getPackageQualifiedName(directory); + if (packageQualifiedName == null) { + return null; + } + final StringBuilder qName = new StringBuilder(packageQualifiedName); + if (qName.length() > 0) { + qName.append("."); + } + qName.append(getBaseName(propertiesFile.getContainingFile())); + return qName.toString(); + } + }); + } + + @NotNull + public Locale getLocale(final @NotNull VirtualFile propertiesFile) { + final String customResourceBundleName = getCustomResourceBundleName(propertiesFile); + + String name = propertiesFile.getName(); + if (customResourceBundleName != null) { + name = name.substring(customResourceBundleName.length()); + } + + final Matcher matcher = PropertiesUtil.LOCALE_PATTERN.matcher(name); + if (matcher.find()) { + final String rawLocale = matcher.group(1); + final String[] splittedRawLocale = rawLocale.split("_"); + if (splittedRawLocale.length > 1 && splittedRawLocale[1].length() >= 2) { + final String language = splittedRawLocale[1]; + final String country = splittedRawLocale.length > 2 ? splittedRawLocale[2] : ""; + final String variant = splittedRawLocale.length > 3 ? splittedRawLocale[3] : ""; + return new Locale(language, country, variant); + } + } + return DEFAULT_LOCALE; + } + + @NotNull + public String getBaseName(@NotNull final PsiFile file) { + return getBaseName(file.getVirtualFile()); + } + + @NotNull + private String getBaseName(@NotNull final VirtualFile file) { + final CustomResourceBundleState customResourceBundle = getCustomResourceBundleState(file); + if (customResourceBundle != null) { + return customResourceBundle.getBaseName(); + } + if (isDefaultDissociated(file)) { + return file.getNameWithoutExtension(); + } + return PropertiesUtil.getDefaultBaseName(file); + } + + + public void dissociateResourceBundle(final @NotNull ResourceBundle resourceBundle) { + if (resourceBundle instanceof CustomResourceBundle) { + final CustomResourceBundleState state = + getCustomResourceBundleState(resourceBundle.getDefaultPropertiesFile().getVirtualFile()); + LOG.assertTrue(state != null); + myState.getCustomResourceBundles().remove(state); + } else { + for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { + final VirtualFile file = propertiesFile.getContainingFile().getVirtualFile(); + myState.getDissociatedFiles().add(file.getUrl()); + } + } + } + + public void combineToResourceBundle(final @NotNull List<PropertiesFile> propertiesFiles, final String baseName) { + myState.getCustomResourceBundles() + .add(new CustomResourceBundleState().addAll(ContainerUtil.map(propertiesFiles, new Function<PropertiesFile, String>() { + @Override + public String fun(PropertiesFile file) { + return file.getVirtualFile().getUrl(); + } + })).setBaseName(baseName)); + } + + @Nullable + public CustomResourceBundle getCustomResourceBundle(final @NotNull PropertiesFile file) { + final VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile == null) { + return null; + } + final CustomResourceBundleState state = getCustomResourceBundleState(virtualFile); + return state == null ? null : CustomResourceBundle.fromState(state, file.getProject()); + } + + public boolean isDefaultDissociated(final @NotNull VirtualFile virtualFile) { + final String url = virtualFile.getUrl(); + return myState.getDissociatedFiles().contains(url) || getCustomResourceBundleState(virtualFile) != null; + } + + @Nullable + private String getCustomResourceBundleName(final @NotNull VirtualFile virtualFile) { + final CustomResourceBundleState customResourceBundle = getCustomResourceBundleState(virtualFile); + return customResourceBundle == null ? null : customResourceBundle.getBaseName(); + } + + @Nullable + private CustomResourceBundleState getCustomResourceBundleState(final @NotNull VirtualFile virtualFile) { + final String url = virtualFile.getUrl(); + for (CustomResourceBundleState customResourceBundleState : myState.getCustomResourceBundles()) { + if (customResourceBundleState.getFileUrls().contains(url)) { + return customResourceBundleState; + } + } + return null; + } + + @Nullable + @Override + public ResourceBundleManagerState getState() { + return myState.isEmpty() ? null : myState; + } + + @Override + public void loadState(ResourceBundleManagerState state) { + myState = state.removeNonExistentFiles(); + } +} |