simplify — use util union
[idea/community.git] / platform / projectModel-impl / src / com / intellij / application / options / PathMacrosCollector.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.application.options;
17
18 import com.intellij.openapi.application.PathMacroFilter;
19 import com.intellij.openapi.application.PathMacros;
20 import com.intellij.openapi.components.CompositePathMacroFilter;
21 import com.intellij.openapi.components.PathMacroMap;
22 import com.intellij.openapi.extensions.ExtensionPointName;
23 import com.intellij.openapi.extensions.Extensions;
24 import com.intellij.openapi.util.text.StringUtil;
25 import com.intellij.util.containers.ContainerUtilRt;
26 import com.intellij.util.containers.SmartHashSet;
27 import org.jdom.Element;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
30
31 import java.util.Collections;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37 /**
38  * @author Eugene Zhuravlev
39  *         Date: Dec 6, 2004
40  */
41 public class PathMacrosCollector extends PathMacroMap {
42   public static final ExtensionPointName<PathMacroFilter> MACRO_FILTER_EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.pathMacroFilter");
43   public static final Pattern MACRO_PATTERN = Pattern.compile("\\$([\\w\\-\\.]+?)\\$");
44
45   private final Matcher myMatcher;
46   private final Map<String, String> myMacroMap = ContainerUtilRt.newLinkedHashMap();
47
48   private PathMacrosCollector() {
49     myMatcher = MACRO_PATTERN.matcher("");
50   }
51
52   @NotNull
53   public static Set<String> getMacroNames(@NotNull final Element e) {
54     return getMacroNames(e, new CompositePathMacroFilter(Extensions.getExtensions(MACRO_FILTER_EXTENSION_POINT_NAME)),
55                          PathMacros.getInstance());
56   }
57
58   @NotNull
59   public static Set<String> getMacroNames(Element root, @Nullable PathMacroFilter filter, @NotNull PathMacros pathMacros) {
60     final PathMacrosCollector collector = new PathMacrosCollector();
61     collector.substitute(root, true, false, filter);
62     Set<String> preResult = collector.myMacroMap.keySet();
63     if (preResult.isEmpty()) {
64       return Collections.emptySet();
65     }
66
67     Set<String> result = new SmartHashSet<>(preResult);
68     result.removeAll(pathMacros.getSystemMacroNames());
69     result.removeAll(pathMacros.getLegacyMacroNames());
70     result.removeAll(PathMacrosImpl.getToolMacroNames());
71     result.removeAll(pathMacros.getIgnoredMacroNames());
72     return result;
73   }
74
75   @NotNull
76   @Override
77   public String substituteRecursively(@NotNull String text, boolean caseSensitive) {
78     if (StringUtil.isEmpty(text)) {
79       return text;
80     }
81
82     myMatcher.reset(text);
83     while (myMatcher.find()) {
84       myMacroMap.put(myMatcher.group(1), null);
85     }
86
87     return text;
88   }
89
90   @Override
91   public String substitute(String text, boolean caseSensitive) {
92     if (StringUtil.isEmpty(text)) {
93       return text;
94     }
95
96     int startPos = -1;
97     if (text.charAt(0) == '$') {
98       startPos = 0;
99     }
100     else {
101       for (String protocol : ReplacePathToMacroMap.PROTOCOLS) {
102         if (text.length() > protocol.length() + 4 && text.startsWith(protocol) && text.charAt(protocol.length()) == ':') {
103           startPos = protocol.length() + 1;
104           if (text.charAt(startPos) == '/') startPos++;
105           if (text.charAt(startPos) == '/') startPos++;
106         }
107       }
108     }
109     if (startPos < 0) {
110       return text;
111     }
112
113     myMatcher.reset(text).region(startPos, text.length());
114     if (myMatcher.lookingAt()) {
115       myMacroMap.put(myMatcher.group(1), null);
116     }
117
118     return text;
119   }
120
121   @Override
122   public int hashCode() {
123     return myMacroMap.hashCode();
124   }
125 }