mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
N^3 logN algorithm
This commit is contained in:
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.update;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
@@ -22,22 +25,18 @@ import java.util.*;
|
||||
* author: lesya
|
||||
*/
|
||||
public class GroupByPackages {
|
||||
|
||||
private final Map<File, Collection<File>> myParentToChildrenMap
|
||||
= new HashMap<File, Collection<File>>();
|
||||
private final Map<File, Collection<File>> myParentToChildrenMap = new HashMap<File, Collection<File>>();
|
||||
private final Collection<File> myRoots = new HashSet<File>();
|
||||
|
||||
public GroupByPackages(Collection<File> fiels) {
|
||||
for (Iterator each = fiels.iterator(); each.hasNext();) {
|
||||
process((File)each.next());
|
||||
public GroupByPackages(@NotNull Collection<File> files) {
|
||||
for (File file : files) {
|
||||
process(file);
|
||||
}
|
||||
|
||||
splitRoots();
|
||||
}
|
||||
|
||||
private void splitRoots() {
|
||||
for (Iterator each = new ArrayList(myRoots).iterator(); each.hasNext();) {
|
||||
File oldRoot = (File)each.next();
|
||||
for (File oldRoot : new ArrayList<File>(myRoots)) {
|
||||
File newRoot = splitRoot(oldRoot);
|
||||
if (!oldRoot.equals(newRoot)) replaceRoot(oldRoot, newRoot);
|
||||
}
|
||||
@@ -48,39 +47,38 @@ public class GroupByPackages {
|
||||
myRoots.add(newRoot);
|
||||
}
|
||||
|
||||
private File splitRoot(File oldRoot) {
|
||||
Collection<File> children = getChildren(oldRoot);
|
||||
if (children == null) return oldRoot;
|
||||
if (children.size() == 1)
|
||||
return splitRoot(children.iterator().next());
|
||||
else {
|
||||
return oldRoot;
|
||||
private File splitRoot(@NotNull File oldRoot) {
|
||||
List<File> children = getChildren(oldRoot);
|
||||
if (children.size() == 1) {
|
||||
return splitRoot(children.get(0));
|
||||
}
|
||||
|
||||
return oldRoot;
|
||||
}
|
||||
|
||||
private void process(File file) {
|
||||
private void process(@NotNull final File file) {
|
||||
File f;
|
||||
File parent = file.getParentFile();
|
||||
if (parent == null) {
|
||||
myRoots.add(file);
|
||||
return;
|
||||
for (f = file; parent != null; f = parent, parent = parent.getParentFile()) {
|
||||
Collection<File> files = myParentToChildrenMap.get(parent);
|
||||
if (files == null) {
|
||||
myParentToChildrenMap.put(parent, files = new HashSet<File>());
|
||||
}
|
||||
files.add(f);
|
||||
}
|
||||
|
||||
if (!myParentToChildrenMap.containsKey(parent)) myParentToChildrenMap.put(parent, new HashSet<File>());
|
||||
myParentToChildrenMap.get(parent).add(file);
|
||||
|
||||
process(parent);
|
||||
myRoots.add(f);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<File> getRoots() {
|
||||
return new ArrayList<File>(myRoots);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<File> getChildren(File file) {
|
||||
Collection<File> collection = myParentToChildrenMap.get(file);
|
||||
if (collection == null)
|
||||
return new ArrayList<File>();
|
||||
else
|
||||
return new ArrayList<File>(collection);
|
||||
if (collection == null) {
|
||||
return ContainerUtil.emptyList();
|
||||
}
|
||||
return new ArrayList<File>(collection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,11 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
private final SimpleTextAttributes myInvalidAttributes;
|
||||
private final Project myProject;
|
||||
|
||||
public GroupTreeNode(String name, boolean supportsDeletion, SimpleTextAttributes invalidAttributes,
|
||||
Project project, final Map<String, String> errorsMap) {
|
||||
public GroupTreeNode(@NotNull String name,
|
||||
boolean supportsDeletion,
|
||||
@NotNull SimpleTextAttributes invalidAttributes,
|
||||
@NotNull Project project,
|
||||
@NotNull Map<String, String> errorsMap) {
|
||||
myName = name;
|
||||
mySupportsDeletion = supportsDeletion;
|
||||
myInvalidAttributes = invalidAttributes;
|
||||
@@ -49,15 +52,20 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
myErrorsMap = errorsMap;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon(boolean expanded) {
|
||||
@NonNls String iconName = expanded ? "folderOpen" : "folder";
|
||||
return IconLoader.getIcon("/nodes/" + iconName + ".png");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<VirtualFile> getVirtualFiles() {
|
||||
ArrayList<VirtualFile> result = new ArrayList<VirtualFile>();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
@@ -66,6 +74,8 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<File> getFiles() {
|
||||
ArrayList<File> result = new ArrayList<File>();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
@@ -74,6 +84,7 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemsCount() {
|
||||
int result = 0;
|
||||
Enumeration children = children();
|
||||
@@ -84,14 +95,18 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean showStatistics() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SimpleTextAttributes getAttributes() {
|
||||
return SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSupportsDeletion() {
|
||||
return mySupportsDeletion;
|
||||
}
|
||||
@@ -104,18 +119,19 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
if (containsGroups()) {
|
||||
rebuildGroups(groupByPackages);
|
||||
}
|
||||
else
|
||||
else {
|
||||
rebuildFiles(groupByPackages);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void rebuildGroups(boolean groupByPackages) {
|
||||
for (int i = 0; i < getChildCount(); i++)
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
((GroupTreeNode)getChildAt(i)).rebuild(groupByPackages);
|
||||
}
|
||||
}
|
||||
|
||||
private void rebuildFiles(boolean groupByPackages) {
|
||||
for (int i = getChildCount()-1; i >= 0; i--) {
|
||||
for (int i = getChildCount() - 1; i >= 0; i--) {
|
||||
final TreeNode node = getChildAt(i);
|
||||
if (node instanceof Disposable) {
|
||||
Disposer.dispose((Disposable)node);
|
||||
@@ -132,12 +148,13 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
|
||||
setTreeModel(myTreeModel);
|
||||
|
||||
if (myTreeModel != null)
|
||||
if (myTreeModel != null) {
|
||||
myTreeModel.nodeStructureChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildPackages() {
|
||||
ArrayList<File> files = new ArrayList<File>();
|
||||
Collection<File> files = new LinkedHashSet<File>();
|
||||
for (final String myFilePath : myFilePaths) {
|
||||
files.add(new File(myFilePath));
|
||||
}
|
||||
@@ -145,21 +162,22 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
|
||||
List<File> roots = groupByPackages.getRoots();
|
||||
addFiles(this, roots, files, groupByPackages, null);
|
||||
|
||||
}
|
||||
|
||||
private void addFiles(AbstractTreeNode parentNode, List<File> roots,
|
||||
final ArrayList<File> files, GroupByPackages groupByPackages, String parentPath) {
|
||||
if (roots == null) return;
|
||||
|
||||
Collections.sort(roots, new Comparator<File>(){
|
||||
public int compare(File file, File file1) {
|
||||
if (files.contains(file) == files.contains(file1))
|
||||
return file.getAbsolutePath().compareToIgnoreCase(file1.getAbsolutePath());
|
||||
else if (files.contains(file))
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
private void addFiles(@NotNull AbstractTreeNode parentNode,
|
||||
@NotNull List<File> roots,
|
||||
@NotNull final Collection<File> files,
|
||||
@NotNull GroupByPackages groupByPackages,
|
||||
String parentPath) {
|
||||
Collections.sort(roots, new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File file1, File file2) {
|
||||
boolean containsFile1 = files.contains(file1);
|
||||
boolean containsFile2 = files.contains(file2);
|
||||
if (containsFile1 == containsFile2) {
|
||||
return file1.getAbsolutePath().compareToIgnoreCase(file2.getAbsolutePath());
|
||||
}
|
||||
return containsFile1 ? 1 : -1;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -167,14 +185,15 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
FileOrDirectoryTreeNode child = files.contains(root)
|
||||
? new FileTreeNode(root.getAbsolutePath(), myInvalidAttributes, myProject, parentPath)
|
||||
: new DirectoryTreeNode(root.getAbsolutePath(), myProject, parentPath);
|
||||
Disposer.register(((Disposable) parentNode), child);
|
||||
Disposer.register((Disposable)parentNode, child);
|
||||
parentNode.add(child);
|
||||
addFiles(child, groupByPackages.getChildren(root), files, groupByPackages, child.getFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
private void buildFiles() {
|
||||
Collections.sort(myFilePaths, new Comparator<String>(){
|
||||
Collections.sort(myFilePaths, new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String path1, String path2) {
|
||||
return path1.compareToIgnoreCase(path2);
|
||||
}
|
||||
@@ -191,10 +210,11 @@ public class GroupTreeNode extends AbstractTreeNode implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsGroups(){
|
||||
private boolean containsGroups() {
|
||||
return myFilePaths.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user