blob: 36ac7dc41ac565c9817ab9d1370254c6e38b5077 [file] [log] [blame]
package com.intellij.openapi.util.io;
import gnu.trove.THashMap;
import gnu.trove.TIntObjectHashMap;
import java.util.*;
/**
* @author yole
*/
public class UniqueNameBuilder<T> {
public static final char INTERNAL_PATH_DELIMITER = '/';
private final Map<T, String> myPaths = new THashMap<T, String>();
private final String mySeparator;
private final int myMaxLength;
private final String myRoot;
public UniqueNameBuilder(String root, String separator, int maxLength) {
myRoot = root;
mySeparator = separator;
myMaxLength = maxLength;
}
private static class Node {
final char myChar;
final TIntObjectHashMap<Node> myChildren;
final Node myParentNode;
Node(char ch, Node parentNode) {
myChar = ch;
myParentNode = parentNode;
myChildren = new TIntObjectHashMap<Node>(1);
}
}
private final Node myRootNode = new Node('\0', null);
public void addPath(T key, String value) {
if (value.startsWith(myRoot)) value = value.substring(myRoot.length());
myPaths.put(key, value);
Node current = myRootNode;
for(int i = value.length() - 1; i >=0; --i) {
char ch = value.charAt(i);
Node node = current.myChildren.get(ch);
if (node == null) current.myChildren.put(ch, node = new Node(ch, current));
current = node;
}
}
public String getShortPath(T key) {
String path = myPaths.get(key);
if (path == null) return key.toString();
Node current = myRootNode, firstDirNodeWithSingleChildAfterNodeWithManyChildren = null;
Node firstDirNode = null;
boolean searchingForManyChildren = current.myChildren.size() == 1;
for(int i = path.length() - 1; i >= 0; --i) {
Node node = current.myChildren.get(path.charAt(i));
if (node == null) return path;
if (firstDirNode == null && node.myChar == INTERNAL_PATH_DELIMITER) {
firstDirNode = node;
}
if (searchingForManyChildren && node.myChildren.size() > 1) {
searchingForManyChildren = false;
} else if (!searchingForManyChildren &&
firstDirNodeWithSingleChildAfterNodeWithManyChildren == null &&
node.myChildren.size() == 1 && node.myChar == INTERNAL_PATH_DELIMITER) {
firstDirNodeWithSingleChildAfterNodeWithManyChildren = node;
}
current = node;
}
if (firstDirNodeWithSingleChildAfterNodeWithManyChildren == null) {
firstDirNodeWithSingleChildAfterNodeWithManyChildren = current;
}
final boolean skipDirs = firstDirNodeWithSingleChildAfterNodeWithManyChildren != firstDirNode;
StringBuilder b = new StringBuilder();
final Node firstCharacterOfDirectoryName = firstDirNodeWithSingleChildAfterNodeWithManyChildren != current || current.myChar==
INTERNAL_PATH_DELIMITER
? firstDirNodeWithSingleChildAfterNodeWithManyChildren.myParentNode // firstDirNodeWithSingleChildAfterNodeWithManyChildren.myChar == /
: firstDirNodeWithSingleChildAfterNodeWithManyChildren;
for(Node n = firstCharacterOfDirectoryName; n != myRootNode; ) {
if (n.myChar == INTERNAL_PATH_DELIMITER) b.append(mySeparator);
else b.append(n.myChar);
if (skipDirs && n.myChar == INTERNAL_PATH_DELIMITER && n != firstDirNode) {
// Skip intermediate path content which is the same till file name
n = n.myParentNode;
while(n != firstDirNode) n = n.myParentNode;
b.append("\u2026").append(mySeparator);
}
n = n.myParentNode;
}
return b.toString();
}
public String getSeparator() {
return mySeparator;
}
}