Lines 60-65
Link Here
|
60 |
import java.util.List; |
60 |
import java.util.List; |
61 |
import java.util.Map; |
61 |
import java.util.Map; |
62 |
import java.util.Set; |
62 |
import java.util.Set; |
|
|
63 |
import java.util.function.Function; |
63 |
import java.util.logging.Level; |
64 |
import java.util.logging.Level; |
64 |
import java.util.logging.Logger; |
65 |
import java.util.logging.Logger; |
65 |
import javax.swing.Icon; |
66 |
import javax.swing.Icon; |
Lines 74-84
Link Here
|
74 |
import org.netbeans.api.queries.SharabilityQuery; |
75 |
import org.netbeans.api.queries.SharabilityQuery; |
75 |
import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton; |
76 |
import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton; |
76 |
import org.netbeans.spi.project.SourceGroupModifierImplementation; |
77 |
import org.netbeans.spi.project.SourceGroupModifierImplementation; |
77 |
import org.netbeans.spi.project.support.ant.AntProjectHelper; |
78 |
import org.netbeans.spi.project.SourceGroupRelativeModifierImplementation; |
78 |
import org.netbeans.spi.project.support.ant.PathMatcher; |
|
|
79 |
import org.netbeans.spi.project.support.ant.PathMatcher; |
80 |
import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
81 |
import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
82 |
import org.netbeans.spi.project.ui.support.ProjectConvertors; |
79 |
import org.netbeans.spi.project.ui.support.ProjectConvertors; |
83 |
import org.openide.filesystems.FileAttributeEvent; |
80 |
import org.openide.filesystems.FileAttributeEvent; |
84 |
import org.openide.filesystems.FileChangeListener; |
81 |
import org.openide.filesystems.FileChangeListener; |
Lines 142-149
Link Here
|
142 |
private final String excludes; |
139 |
private final String excludes; |
143 |
private final String hint; |
140 |
private final String hint; |
144 |
private boolean removed; // just for sanity checking |
141 |
private boolean removed; // just for sanity checking |
145 |
|
142 |
private final String[] projectParts; |
146 |
public SourceRoot(String location, String includes, String excludes, String hint, String displayName, Icon icon, Icon openedIcon) { |
143 |
|
|
|
144 |
public SourceRoot(String location, String includes, String excludes, String hint, String displayName, Icon icon, Icon openedIcon, String[] parts) { |
147 |
super(location); |
145 |
super(location); |
148 |
this.displayName = displayName; |
146 |
this.displayName = displayName; |
149 |
this.icon = icon; |
147 |
this.icon = icon; |
Lines 151-156
Link Here
|
151 |
this.includes = includes; |
149 |
this.includes = includes; |
152 |
this.excludes = excludes; |
150 |
this.excludes = excludes; |
153 |
this.hint = hint; |
151 |
this.hint = hint; |
|
|
152 |
this.projectParts = parts; |
154 |
removed = false; |
153 |
removed = false; |
155 |
} |
154 |
} |
156 |
|
155 |
|
Lines 322-329
Link Here
|
322 |
|
321 |
|
323 |
private final class TypedSourceRoot extends SourceRoot { |
322 |
private final class TypedSourceRoot extends SourceRoot { |
324 |
private final String type; |
323 |
private final String type; |
325 |
public TypedSourceRoot(String type, String hint, String location, String includes, String excludes, String displayName, Icon icon, Icon openedIcon) { |
324 |
public TypedSourceRoot(String type, String hint, String location, String includes, String excludes, String displayName, Icon icon, Icon openedIcon, String[] parts) { |
326 |
super(location, includes, excludes, hint, displayName, icon, openedIcon); |
325 |
super(location, includes, excludes, hint, displayName, icon, openedIcon, parts); |
327 |
this.type = type; |
326 |
this.type = type; |
328 |
} |
327 |
} |
329 |
public final String getType() { |
328 |
public final String getType() { |
Lines 404-409
Link Here
|
404 |
private String excludes; |
403 |
private String excludes; |
405 |
private String type; |
404 |
private String type; |
406 |
private String hint; |
405 |
private String hint; |
|
|
406 |
private String[] parts; |
407 |
|
407 |
|
408 |
private SourceRootConfig(String location) { |
408 |
private SourceRootConfig(String location) { |
409 |
this.location = location; |
409 |
this.location = location; |
Lines 505-510
Link Here
|
505 |
openedIcon = value; |
505 |
openedIcon = value; |
506 |
return this; |
506 |
return this; |
507 |
} |
507 |
} |
|
|
508 |
|
509 |
/** |
510 |
* Declares that the source root resides in some (hierarchical) project part. |
511 |
* The project can be partitioned on multiple levels, each source root may represent some |
512 |
* part of the project. Partitioning can be used to identify "sibling" roots |
513 |
* @param parts abstract location of this root |
514 |
* @return {@code this} |
515 |
* @since 1.68 |
516 |
*/ |
517 |
public SourceRootConfig inParts(String... parts) { |
518 |
this.parts = parts; |
519 |
return this; |
520 |
} |
508 |
|
521 |
|
509 |
/** |
522 |
/** |
510 |
* Adds configured source root to <code>SourcesHelper</code>. |
523 |
* Adds configured source root to <code>SourcesHelper</code>. |
Lines 519-527
Link Here
|
519 |
throw new IllegalStateException("registerExternalRoots was already called"); // NOI18N |
532 |
throw new IllegalStateException("registerExternalRoots was already called"); // NOI18N |
520 |
} |
533 |
} |
521 |
if (type != null) { |
534 |
if (type != null) { |
522 |
typedSourceRoots.add(new TypedSourceRoot(type, hint, location, includes, excludes, displayName, icon, openedIcon)); |
535 |
typedSourceRoots.add(new TypedSourceRoot(type, hint, location, includes, excludes, displayName, icon, openedIcon, parts)); |
523 |
} else { |
536 |
} else { |
524 |
principalSourceRoots.add(new SourceRoot(location, includes, excludes, hint, displayName, icon, openedIcon)); |
537 |
principalSourceRoots.add(new SourceRoot(location, includes, excludes, hint, displayName, icon, openedIcon, parts)); |
525 |
} |
538 |
} |
526 |
return this; |
539 |
return this; |
527 |
} |
540 |
} |
Lines 951-957
Link Here
|
951 |
if (type.equals(Sources.TYPE_GENERIC)) { |
964 |
if (type.equals(Sources.TYPE_GENERIC)) { |
952 |
List<SourceRoot> roots = new ArrayList<SourceRoot>(principalSourceRoots); |
965 |
List<SourceRoot> roots = new ArrayList<SourceRoot>(principalSourceRoots); |
953 |
// Always include the project directory itself as a default: |
966 |
// Always include the project directory itself as a default: |
954 |
roots.add(new SourceRoot("", null, null, null, ProjectUtils.getInformation(getProject()).getDisplayName(), null, null)); |
967 |
roots.add(new SourceRoot("", null, null, null, ProjectUtils.getInformation(getProject()).getDisplayName(), null, null, null)); |
955 |
Map<FileObject,SourceRoot> rootsByDir = new LinkedHashMap<FileObject,SourceRoot>(); |
968 |
Map<FileObject,SourceRoot> rootsByDir = new LinkedHashMap<FileObject,SourceRoot>(); |
956 |
// First collect all non-redundant existing roots. |
969 |
// First collect all non-redundant existing roots. |
957 |
for (SourceRoot r : roots) { |
970 |
for (SourceRoot r : roots) { |
Lines 1120-1130
Link Here
|
1120 |
public SourceGroupModifierImplementation createSourceGroupModifierImplementation() { |
1133 |
public SourceGroupModifierImplementation createSourceGroupModifierImplementation() { |
1121 |
return new SourceGroupModifierImpl(); |
1134 |
return new SourceGroupModifierImpl(); |
1122 |
} |
1135 |
} |
|
|
1136 |
|
1137 |
private static final class Key implements Function<SourceRoot, Integer> { |
1138 |
private SourceRoot root; |
1139 |
private String[] parts; |
1140 |
|
1141 |
public Key(SourceRoot root, String[] parts) { |
1142 |
this.root = root; |
1143 |
this.parts = parts; |
1144 |
} |
1145 |
|
1146 |
public Integer apply(SourceRoot r) { |
1147 |
int result = 0; |
1148 |
int start = 0; |
1149 |
if (this.root != null) { |
1150 |
if (root.projectParts != null && r.projectParts != null) { |
1151 |
for (int i = 0; i < root.projectParts.length && i < r.projectParts.length; i++) { |
1152 |
if (root.projectParts[i].equals(r.projectParts[i])) { |
1153 |
start++; |
1154 |
} else { |
1155 |
break; |
1156 |
} |
1157 |
} |
1158 |
} |
1159 |
} |
1160 |
if (parts != null && r.projectParts != null) { |
1161 |
for (int i = start; i < parts.length && i < r.projectParts.length; i++) { |
1162 |
if (parts[i].equals(r.projectParts[i])) { |
1163 |
result++; |
1164 |
} else { |
1165 |
break; |
1166 |
} |
1167 |
} |
1168 |
} |
1169 |
return result + start; |
1170 |
} |
1171 |
} |
1172 |
|
1173 |
private class SourceGroupModifierImpl implements SourceGroupModifierImplementation, SourceGroupRelativeModifierImplementation { |
1174 |
private final Function<SourceRoot, Integer> similarity; |
1123 |
|
1175 |
|
1124 |
private class SourceGroupModifierImpl implements SourceGroupModifierImplementation { |
1176 |
public SourceGroupModifierImpl() { |
1125 |
|
1177 |
this(null); |
|
|
1178 |
} |
1179 |
|
1180 |
public SourceGroupModifierImpl(Function<SourceRoot, Integer> similarity) { |
1181 |
this.similarity = similarity; |
1182 |
} |
1183 |
|
1126 |
public SourceGroup createSourceGroup(String type, String hint) { |
1184 |
public SourceGroup createSourceGroup(String type, String hint) { |
1127 |
SourceRoot root = findRoot(type, hint); |
1185 |
SourceRoot root = findRoot(type, hint, similarity); |
1128 |
if (root == null) |
1186 |
if (root == null) |
1129 |
return null; |
1187 |
return null; |
1130 |
if (root.isRemoved()) |
1188 |
if (root.isRemoved()) |
Lines 1151-1175
Link Here
|
1151 |
} |
1209 |
} |
1152 |
|
1210 |
|
1153 |
public boolean canCreateSourceGroup(String type, String hint) { |
1211 |
public boolean canCreateSourceGroup(String type, String hint) { |
1154 |
return findRoot(type, hint) != null; |
1212 |
return findRoot(type, hint, similarity) != null; |
1155 |
} |
1213 |
} |
1156 |
private SourceRoot findRoot(String type, String hint) { |
1214 |
|
|
|
1215 |
private SourceRoot findRoot(String type, String hint, Function<SourceRoot, Integer> similarity) { |
1216 |
int maxSimilarity = -1; |
1217 |
SourceRoot candidate = null; |
1218 |
|
1157 |
if (Sources.TYPE_GENERIC.equals(type)) { |
1219 |
if (Sources.TYPE_GENERIC.equals(type)) { |
1158 |
for (SourceRoot root : principalSourceRoots) { |
1220 |
for (SourceRoot root : principalSourceRoots) { |
1159 |
if (root.getHint() != null |
1221 |
if (root.getHint() != null |
1160 |
&& root.getHint().equals(hint) |
1222 |
&& root.getHint().equals(hint) |
1161 |
&& ! root.isRemoved()) |
1223 |
&& ! root.isRemoved()) { |
1162 |
return root; |
1224 |
if (similarity == null) { |
|
|
1225 |
return root; |
1226 |
} else { |
1227 |
int sim = similarity.apply(root); |
1228 |
if (sim > maxSimilarity) { |
1229 |
candidate = root; |
1230 |
maxSimilarity = sim; |
1231 |
} |
1232 |
} |
1233 |
} |
1163 |
} |
1234 |
} |
1164 |
} else { |
1235 |
} else { |
1165 |
for (TypedSourceRoot root : typedSourceRoots) { |
1236 |
for (TypedSourceRoot root : typedSourceRoots) { |
1166 |
if (root.getHint() != null |
1237 |
if (root.getHint() != null |
1167 |
&& root.getType().equals(type) |
1238 |
&& root.getType().equals(type) |
1168 |
&& root.getHint().equals(hint)) |
1239 |
&& root.getHint().equals(hint)) { |
1169 |
return root; |
1240 |
if (similarity == null) { |
|
|
1241 |
return root; |
1242 |
} else { |
1243 |
int sim = similarity.apply(root); |
1244 |
if (sim > maxSimilarity) { |
1245 |
candidate = root; |
1246 |
maxSimilarity = sim; |
1247 |
} |
1248 |
} |
1249 |
} |
1170 |
} |
1250 |
} |
1171 |
} |
1251 |
} |
1172 |
return null; |
1252 |
return candidate; |
|
|
1253 |
} |
1254 |
|
1255 |
public SourceGroupModifierImplementation relativeTo(SourceGroup existingGroup, String... projectPart) { |
1256 |
SourceRoot origin = null; |
1257 |
if (existingGroup != null) { |
1258 |
FileObject fo = existingGroup.getRootFolder(); |
1259 |
File f = FileUtil.toFile(fo); |
1260 |
for (SourceRoot r : principalSourceRoots) { |
1261 |
File loc = r.getActualLocation(); |
1262 |
if (loc != null && loc.equals(f)) { |
1263 |
origin = r; |
1264 |
break; |
1265 |
} |
1266 |
} |
1267 |
} |
1268 |
return new SourceGroupModifierImpl(new Key(origin, projectPart)); |
1173 |
} |
1269 |
} |
1174 |
} |
1270 |
} |
1175 |
|
1271 |
|