/*
* Copyright 2013 Vladimir Rudev
*
* 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 ru.crazyproger.plugins.webtoper.nls.psi;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.PropertiesFileType;
import com.intellij.lang.properties.psi.impl.PropertiesFileImpl;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.crazyproger.plugins.webtoper.nls.NlsUtils;
import ru.crazyproger.plugins.webtoper.nls.psi.impl.NlsNameImpl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class NlsFileImpl extends PropertiesFileImpl {
public NlsFileImpl(FileViewProvider viewProvider) {
super(viewProvider);
}
@Override
public String toString() {
return "Nls file: " + getName();
}
public Collection<NlsNameImpl> getIncludes() {
return PsiTreeUtil.findChildrenOfType(this, NlsNameImpl.class);
}
@NotNull
public Collection<NlsFileImpl> getIncludedFiles() {
Collection<NlsNameImpl> includes = getIncludes();
if (includes == null || includes.isEmpty()) {
return Collections.emptyList();
}
List<NlsFileImpl> included = new ArrayList<NlsFileImpl>(includes.size());
for (NlsNameImpl include : includes) {
PsiReference reference = include.getReference();
if (reference == null) {
continue;
}
PsiElement resolved = reference.resolve();
if (resolved != null) {
included.add((NlsFileImpl) resolved);
}
}
return included;
}
public Collection<IProperty> getAllProperties() {
return getAllPropertiesRecursive(Sets.<NlsFileImpl>newHashSet(this));
}
private Collection<IProperty> getAllPropertiesRecursive(@NotNull Set<NlsFileImpl> processedFiles) { // todo #WT-30
Collection<NlsFileImpl> includedFiles = getIncludedFiles();
Map<String, IProperty> keyToProperty = Maps.newHashMap();
for (NlsFileImpl nlsFile : includedFiles) { // order matters!
if (processedFiles.contains(nlsFile)) {
continue;
}
processedFiles.add(nlsFile);
Collection<IProperty> fileProperties = nlsFile.getAllPropertiesRecursive(processedFiles);
addPropertiesToMap(fileProperties, keyToProperty);
}
addPropertiesToMap(getProperties(), keyToProperty);
return keyToProperty.values();
}
@Nullable
public String getNlsName() {
for (VirtualFile folder : NlsUtils.getAllNlsRoots(getProject())) {
if (folder != null) {
VirtualFile file = getVirtualFile();
assert file != null;
if (VfsUtil.isAncestor(folder, file, true)) {
String relativePath = FileUtil.getRelativePath(folder.getPath(), file.getPath(), '/');
assert relativePath != null : "relative path must be";
String dottedPath = relativePath.replaceAll("/", ".");
return StringUtil.trimEnd(dottedPath, PropertiesFileType.DOT_DEFAULT_EXTENSION);
}
}
}
return null;
}
private void addPropertiesToMap(Collection<IProperty> fileProperties, Map<String, IProperty> properties) {
for (IProperty fileProperty : fileProperties) {
String key = fileProperty.getKey();
if (key != null) {
properties.put(key, fileProperty);
}
}
}
public static class PropertyKeyEqualsPredicate implements Predicate<IProperty> {
private final String key;
public PropertyKeyEqualsPredicate(String key) {
this.key = key;
}
@Override
public boolean apply(@Nullable IProperty iProperty) {
return iProperty != null && key.equals(iProperty.getKey());
}
}
public static class Property2PsiElementFunction implements Function<IProperty, PsiElement> {
@Override
public PsiElement apply(@Nullable IProperty iProperty) {
if (iProperty != null) {
return iProperty.getPsiElement();
}
return null;
}
}
}