2 * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
3 * Use is subject to license terms.
5 package com
.intellij
.application
.options
;
7 import com
.intellij
.openapi
.components
.PathMacroMap
;
8 import com
.intellij
.openapi
.util
.text
.StringUtil
;
9 import com
.intellij
.util
.StringBuilderSpinAllocator
;
14 * @author Eugene Zhuravlev
17 public class ReplacePathToMacroMap
extends PathMacroMap
{
18 final Set
<String
> myUsedMacros
= new HashSet
<String
>();
19 List
<String
> myPathsIndex
= null;
20 private static final Comparator
<String
> PATHS_COMPARATOR
= new Comparator
<String
>() {
21 public int compare(final String o1
, final String o2
) {
22 return o2
.length() - o1
.length();
26 public void addMacroReplacement(String path
, String macroName
) {
27 put(quotePath(path
), "$" + macroName
+ "$");
30 public String
substitute(String text
, boolean caseSensitive
) {
31 for (final String path
: getPathIndex()) {
32 final String macro
= get(path
);
33 text
= replacePathMacro(text
, path
, macro
, caseSensitive
);
38 private String
replacePathMacro(String text
, String path
, final String macro
, boolean caseSensitive
) {
39 if (text
.length() < path
.length()) {
43 if (path
.length() == 0) return text
;
45 final StringBuilder newText
= StringBuilderSpinAllocator
.alloc();
47 final boolean isWindowsRoot
= path
.endsWith(":/");
49 while (i
< text
.length()) {
50 int occurrenceOfPath
= caseSensitive ? text
.indexOf(path
, i
) : StringUtil
.indexOfIgnoreCase(text
, path
, i
);
51 if (occurrenceOfPath
>= 0) {
52 int endOfOccurence
= occurrenceOfPath
+ path
.length();
53 if (!isWindowsRoot
&& endOfOccurence
< text
.length() && text
.charAt(endOfOccurence
) != '/') {
58 if (occurrenceOfPath
< 0) {
59 if (newText
.length() == 0) {
62 newText
.append(text
.substring(i
));
66 newText
.append(text
.substring(i
, occurrenceOfPath
));
67 newText
.append(macro
);
69 i
= occurrenceOfPath
+ path
.length();
72 return newText
.toString();
75 StringBuilderSpinAllocator
.dispose(newText
);
79 private void logUsage(String macroReplacement
) {
80 if (macroReplacement
.length() >= 2 && macroReplacement
.startsWith("$") && macroReplacement
.endsWith("$")) {
81 macroReplacement
= macroReplacement
.substring(1, macroReplacement
.length() - 1);
83 myUsedMacros
.add(macroReplacement
);
86 public Set
<String
> getUsedMacroNames() {
87 final Set
<String
> userMacroNames
= PathMacrosImpl
.getInstanceEx().getUserMacroNames();
88 final Set
<String
> used
= new HashSet
<String
>(myUsedMacros
);
89 used
.retainAll(userMacroNames
);
93 private List
<String
> getPathIndex() {
94 if (myPathsIndex
== null || myPathsIndex
.size() != size()) {
95 myPathsIndex
= new ArrayList
<String
>(keySet());
96 // sort so that lenthy paths are traversed first
97 // so from the 2 strings such that one is a substring of another the one that dominates is substituted first
98 Collections
.sort(myPathsIndex
, PATHS_COMPARATOR
);
103 public boolean equals(Object obj
) {
104 if (obj
== this) return true;
105 if (!(obj
instanceof ReplacePathToMacroMap
)) return false;
107 return myMacroMap
.equals(((ReplacePathToMacroMap
)obj
).myMacroMap
);
110 public int hashCode() {
111 return myMacroMap
.hashCode();