| /* |
| * 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.structureView; |
| |
| import com.intellij.icons.AllIcons; |
| import com.intellij.ide.structureView.StructureViewTreeElement; |
| import com.intellij.ide.util.treeView.AbstractTreeNode; |
| import com.intellij.ide.util.treeView.smartTree.*; |
| import com.intellij.lang.properties.IProperty; |
| import com.intellij.lang.properties.PropertiesBundle; |
| import com.intellij.lang.properties.editor.ResourceBundlePropertyStructureViewElement; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.Comparing; |
| import com.intellij.openapi.util.text.StringUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.*; |
| |
| /** |
| * @author cdr |
| */ |
| public class GroupByWordPrefixes implements Grouper, Sorter { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.lang.properties.structureView.GroupByWordPrefixes"); |
| @NonNls public static final String ID = "GROUP_BY_PREFIXES"; |
| private String mySeparator; |
| |
| public GroupByWordPrefixes(String separator) { |
| mySeparator = separator; |
| } |
| |
| public void setSeparator(final String separator) { |
| mySeparator = separator; |
| } |
| |
| public String getSeparator() { |
| return mySeparator; |
| } |
| |
| @Override |
| @NotNull |
| public Collection<Group> group(@NotNull final AbstractTreeNode parent, @NotNull Collection<TreeElement> children) { |
| List<Key> keys = new ArrayList<Key>(); |
| |
| String parentPrefix; |
| int parentPrefixLength; |
| if (parent.getValue() instanceof PropertiesPrefixGroup) { |
| parentPrefix = ((PropertiesPrefixGroup)parent.getValue()).getPrefix(); |
| parentPrefixLength = StringUtil.split(parentPrefix, mySeparator).size(); |
| } |
| else { |
| parentPrefix = ""; |
| parentPrefixLength = 0; |
| } |
| for (TreeElement element : children) { |
| if (!(element instanceof StructureViewTreeElement)) { |
| continue; |
| } |
| final Object value = ((StructureViewTreeElement)element).getValue(); |
| if (!(value instanceof IProperty)) { |
| continue; |
| } |
| final String text = ((IProperty) value).getUnescapedKey(); |
| if (text == null) continue; |
| LOG.assertTrue(text.startsWith(parentPrefix) || text.startsWith(mySeparator)); |
| List<String> words = StringUtil.split(text, mySeparator); |
| keys.add(new Key(words, element)); |
| } |
| Collections.sort(keys, new Comparator<Key>() { |
| @Override |
| public int compare(final Key k1, final Key k2) { |
| List<String> o1 = k1.words; |
| List<String> o2 = k2.words; |
| for (int i = 0; i < Math.max(o1.size(), o2.size()); i++) { |
| if (i == o1.size()) return 1; |
| if (i == o2.size()) return -1; |
| String s1 = o1.get(i); |
| String s2 = o2.get(i); |
| int res = s1.compareTo(s2); |
| if (res != 0) return res; |
| } |
| return 0; |
| } |
| }); |
| List<Group> groups = new ArrayList<Group>(); |
| int groupStart = 0; |
| for (int i = 0; i <= keys.size(); i++) { |
| if (!isEndOfGroup(i, keys, parentPrefixLength)) { |
| continue; |
| } |
| // find longest group prefix |
| List<String> firstKey = groupStart == keys.size() ? Collections.<String>emptyList() : keys.get(groupStart).words; |
| int prefixLen = firstKey.size(); |
| for (int j = groupStart+1; j < i; j++) { |
| List<String> prevKey = keys.get(j-1).words; |
| List<String> nextKey = keys.get(j).words; |
| for (int k = parentPrefixLength; k < prefixLen; k++) { |
| String word = k < nextKey.size() ? nextKey.get(k) : null; |
| String wordInPrevKey = k < prevKey.size() ? prevKey.get(k) : null; |
| if (!Comparing.strEqual(word, wordInPrevKey)) { |
| prefixLen = k; |
| break; |
| } |
| } |
| } |
| String[] strings = firstKey.subList(0,prefixLen).toArray(new String[prefixLen]); |
| String prefix = StringUtil.join(strings, mySeparator); |
| String presentableName = prefix.substring(parentPrefix.length()); |
| presentableName = StringUtil.trimStart(presentableName, mySeparator); |
| if (i - groupStart > 1) { |
| groups.add(new PropertiesPrefixGroup(children, prefix, presentableName, mySeparator)); |
| } |
| else if (groupStart != keys.size()) { |
| TreeElement node = keys.get(groupStart).node; |
| if (node instanceof PropertiesStructureViewElement) { |
| ((PropertiesStructureViewElement)node).setPresentableName(presentableName); |
| } |
| else { |
| ((ResourceBundlePropertyStructureViewElement)node).setPresentableName(presentableName); |
| } |
| } |
| groupStart = i; |
| } |
| return groups; |
| } |
| |
| private static boolean isEndOfGroup(final int i, |
| final List<Key> keys, |
| final int parentPrefixLength) { |
| if (i == keys.size()) return true; |
| if (i == 0) return false; |
| List<String> words = keys.get(i).words; |
| List<String> prevWords = keys.get(i - 1).words; |
| if (prevWords.size() == parentPrefixLength) return true; |
| if (words.size() == parentPrefixLength) return true; |
| return !Comparing.strEqual(words.get(parentPrefixLength), prevWords.get(parentPrefixLength)); |
| } |
| |
| @Override |
| @NotNull |
| public ActionPresentation getPresentation() { |
| return new ActionPresentationData(PropertiesBundle.message("structure.view.group.by.prefixes.action.name"), |
| PropertiesBundle.message("structure.view.group.by.prefixes.action.description"), |
| AllIcons.Actions.GroupByPrefix); |
| } |
| |
| @Override |
| @NotNull |
| public String getName() { |
| return ID; |
| } |
| |
| @NotNull |
| @Override |
| public Comparator getComparator() { |
| return Sorter.ALPHA_SORTER.getComparator(); |
| } |
| |
| @Override |
| public boolean isVisible() { |
| return true; |
| } |
| |
| private static class Key { |
| final List<String> words; |
| final TreeElement node; |
| |
| public Key(final List<String> words, final TreeElement node) { |
| this.words = words; |
| this.node = node; |
| } |
| } |
| |
| } |