Changeset 18823 in josm
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetSelector.java
r18691 r18823 9 9 import java.awt.event.ActionEvent; 10 10 import java.util.ArrayList; 11 import java.util.Arrays; 11 12 import java.util.Collection; 12 13 import java.util.Collections; … … 64 65 65 66 private static final Pattern PATTERN_PUNCTUATION = Pattern.compile("\\p{Punct}", Pattern.UNICODE_CHARACTER_CLASS); 67 private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s", Pattern.UNICODE_CHARACTER_CLASS); 66 68 67 69 private static final BooleanProperty SEARCH_IN_TAGS = new BooleanProperty("taggingpreset.dialog.search-in-tags", true); … … 90 92 */ 91 93 public static class PresetClassification implements Comparable<PresetClassification> { 94 /** The preset for this classification object */ 92 95 public final TaggingPreset preset; 96 /** 97 * The classification for the preset (see {@link #CLASSIFICATION_TAGS_MATCH}, {@link #CLASSIFICATION_GROUP_MATCH}, 98 * {@link #CLASSIFICATION_NAME_MATCH}, and {@link #CLASSIFICATION_IN_FAVORITES}). Higher numbers are better. 99 */ 93 100 public int classification; 101 /** 102 * The index in favorites, index = {@link #CLASSIFICATION_IN_FAVORITES} - favoriteIndex 103 */ 94 104 public int favoriteIndex; 95 private final Collection<String> groups; 96 private final Collection<String> names; 97 private final Collection<String> tags; 105 /** Groups that have been run through {@link #simplifyString(String)} */ 106 private final String[] groupsSimplified; 107 /** Names that have been run through {@link #simplifyString(String)}*/ 108 private final String[] namesSimplified; 109 /** Tags that have been run through {@link #simplifyString(String)} */ 110 private final String[] tagsSimplified; 98 111 99 112 PresetClassification(TaggingPreset preset) { … … 126 139 } 127 140 } 128 this.groups = Utils.toUnmodifiableList(groupSet); 129 this.names = Utils.toUnmodifiableList(nameSet); 130 this.tags = Utils.toUnmodifiableList(tagSet); 141 // These should be "frozen" arrays 142 this.groupsSimplified = groupSet.stream().map(PresetClassification::simplifyString) 143 .toArray(String[]::new); 144 this.namesSimplified = nameSet.stream().map(PresetClassification::simplifyString) 145 .toArray(String[]::new); 146 this.tagsSimplified = tagSet.stream().map(PresetClassification::simplifyString) 147 .toArray(String[]::new); 131 148 } 132 149 … … 134 151 String locName = preset.getLocaleName(); 135 152 if (locName != null) { 136 Collections.addAll(collection, locName.toLowerCase(Locale.ENGLISH).split("\\s", -1));153 Collections.addAll(collection, PATTERN_WHITESPACE.split(locName.toLowerCase(Locale.ENGLISH), -1)); 137 154 } 138 155 } … … 142 159 } 143 160 144 private static int isMatching(Collection<String> values, String... searchString) { 161 /** 162 * Check to see if the search string matches values 163 * @param deaccentedValues Values that have been simplified 164 * @param deaccentedSearchString The simplified search string to use 165 * @return The number used for sorting hits (bigger == more matches) 166 */ 167 private static int isMatching(String[] deaccentedValues, String... deaccentedSearchString) { 145 168 int sum = 0; 146 List<String> deaccentedValues = values.stream() 147 .map(PresetClassification::simplifyString).collect(Collectors.toList()); 148 for (String word: searchString) { 169 for (String deaccentedWord: deaccentedSearchString) { 149 170 boolean found = false; 150 171 boolean foundFirst = false; 151 String deaccentedWord = simplifyString(word);152 172 for (String value: deaccentedValues) { 153 173 int index = value.indexOf(deaccentedWord); … … 169 189 } 170 190 171 int isMatchingGroup(String... words) {172 return isMatching(groups , words);173 } 174 175 int isMatchingName(String... words) {176 return isMatching(names , words);177 } 178 179 int isMatchingTags(String... words) {180 return isMatching(tags , words);191 private int isMatchingGroup(String... words) { 192 return isMatching(groupsSimplified, words); 193 } 194 195 private int isMatchingName(String... words) { 196 return isMatching(namesSimplified, words); 197 } 198 199 private int isMatchingTags(String... words) { 200 return isMatching(tagsSimplified, words); 181 201 } 182 202 … … 188 208 else 189 209 return result; 210 } 211 212 @Override 213 public int hashCode() { 214 return this.preset.hashCode() + 31 * (Integer.hashCode(this.classification) 215 + 31 * Integer.hashCode(this.favoriteIndex)); 216 } 217 218 @Override 219 public boolean equals(Object obj) { 220 if (this.getClass().isInstance(obj)) { 221 PresetClassification other = (PresetClassification) obj; 222 return this.preset.equals(other.preset) && this.classification == other.classification 223 && this.favoriteIndex == other.favoriteIndex; 224 } 225 return false; 190 226 } 191 227 … … 257 293 258 294 DataSet ds = OsmDataManager.getInstance().getEditDataSet(); 259 Collection<OsmPrimitive> selected = (ds == null) ? Collections. <OsmPrimitive>emptyList() : ds.getSelected();295 Collection<OsmPrimitive> selected = (ds == null) ? Collections.emptyList() : ds.getSelected(); 260 296 final List<PresetClassification> result = classifications.getMatchingPresets( 261 297 text, onlyApplicable, inTags, getTypesInSelection(), selected); … … 277 313 */ 278 314 public static class PresetClassifications implements Iterable<PresetClassification> { 279 280 private final List<PresetClassification> classifications = new ArrayList<>(); 281 315 private static final PresetClassification[] EMPTY_PRESET_CLASSIFICATION = new PresetClassification[0]; 316 private PresetClassification[] classifications = EMPTY_PRESET_CLASSIFICATION; 317 318 /** 319 * Get matching presets 320 * @param searchText The text to search for 321 * @param onlyApplicable Only look for presets that are applicable to the selection 322 * @param inTags Search for names in tags 323 * @param presetTypes The preset types to look for, may be {@code null} 324 * @param selectedPrimitives The primitives to filter on, must not be {@code null} 325 * if {@code onlyApplicable} is {@code true} 326 * @return The matching presets in a sorted list based off of relevance. 327 */ 282 328 public List<PresetClassification> getMatchingPresets(String searchText, boolean onlyApplicable, boolean inTags, 283 329 Set<TaggingPresetType> presetTypes, final Collection<? extends OsmPrimitive> selectedPrimitives) { … … 286 332 287 333 if (searchText.contains("/")) { 288 groupWords = searchText.substring(0, searchText.lastIndexOf('/')).split(" [\\s/]", -1);289 nameWords = searchText.substring(searchText.indexOf('/') + 1).split("\\s", -1);334 groupWords = searchText.substring(0, searchText.lastIndexOf('/')).split("(?U)[\\s/]", -1); 335 nameWords = PATTERN_WHITESPACE.split(searchText.substring(searchText.indexOf('/') + 1), -1); 290 336 } else { 291 337 groupWords = null; 292 nameWords = searchText.split("\\s", -1);338 nameWords = PATTERN_WHITESPACE.split(searchText, -1); 293 339 } 294 340 … … 296 342 } 297 343 344 /** 345 * Get matching presets 346 * @param groupWords The groups to search for 347 * @param nameWords The names to search for, may look in tags if {@code inTags} is {@code true} 348 * @param onlyApplicable Only look for presets that are applicable to the selection 349 * @param inTags Search for names in tags 350 * @param presetTypes The preset types to look for, may be {@code null} 351 * @param selectedPrimitives The primitives to filter on, must not be {@code null} 352 * if {@code onlyApplicable} is {@code true} 353 * @return The matching presets in a sorted list based off of relevance. 354 */ 298 355 public List<PresetClassification> getMatchingPresets(String[] groupWords, String[] nameWords, boolean onlyApplicable, 299 356 boolean inTags, Set<TaggingPresetType> presetTypes, final Collection<? extends OsmPrimitive> selectedPrimitives) { 300 357 301 358 final List<PresetClassification> result = new ArrayList<>(); 359 final String[] simplifiedGroupWords = groupWords == null ? null : 360 Arrays.stream(groupWords).map(PresetClassification::simplifyString).toArray(String[]::new); 361 final String[] simplifiedNameWords = nameWords == null ? null : 362 Arrays.stream(nameWords).map(PresetClassification::simplifyString).toArray(String[]::new); 302 363 for (PresetClassification presetClassification : classifications) { 303 364 TaggingPreset preset = presetClassification.preset; … … 318 379 } 319 380 320 if ( groupWords != null && presetClassification.isMatchingGroup(groupWords) == 0) {381 if (simplifiedGroupWords != null && presetClassification.isMatchingGroup(simplifiedGroupWords) == 0) { 321 382 continue; 322 383 } 323 384 324 int matchName = presetClassification.isMatchingName( nameWords);385 int matchName = presetClassification.isMatchingName(simplifiedNameWords); 325 386 326 387 if (matchName == 0) { 327 if ( groupWords == null) {328 int groupMatch = presetClassification.isMatchingGroup( nameWords);388 if (simplifiedGroupWords == null) { 389 int groupMatch = presetClassification.isMatchingGroup(simplifiedNameWords); 329 390 if (groupMatch > 0) { 330 391 presetClassification.classification = CLASSIFICATION_GROUP_MATCH + groupMatch; … … 332 393 } 333 394 if (presetClassification.classification == 0 && inTags) { 334 int tagsMatch = presetClassification.isMatchingTags( nameWords);395 int tagsMatch = presetClassification.isMatchingTags(simplifiedNameWords); 335 396 if (tagsMatch > 0) { 336 397 presetClassification.classification = CLASSIFICATION_TAGS_MATCH + tagsMatch; … … 355 416 */ 356 417 public void clear() { 357 classifications .clear();418 classifications = EMPTY_PRESET_CLASSIFICATION; 358 419 } 359 420 … … 363 424 */ 364 425 public void loadPresets(Collection<TaggingPreset> presets) { 426 final List<PresetClassification> classificationList = new ArrayList<>(presets.size()); 365 427 for (TaggingPreset preset : presets) { 366 428 if (preset instanceof TaggingPresetSeparator || preset instanceof TaggingPresetMenu) { 367 429 continue; 368 430 } 369 classifications.add(new PresetClassification(preset)); 370 } 431 classificationList.add(new PresetClassification(preset)); 432 } 433 classifications = classificationList.toArray(new PresetClassification[0]); 371 434 } 372 435 373 436 @Override 374 437 public Iterator<PresetClassification> iterator() { 375 return classifications.iterator();438 return Arrays.stream(classifications).iterator(); 376 439 } 377 440 } -
trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetSelectorTest.java
r17275 r18823 2 2 package org.openstreetmap.josm.gui.tagging.presets; 3 3 4 import static org.junit.jupiter.api.Assertions.assert Equals;4 import static org.junit.jupiter.api.Assertions.assertSame; 5 5 import static org.junit.jupiter.api.Assertions.assertTrue; 6 6 7 import org.junit.jupiter.api.extension.RegisterExtension; 7 import java.util.Collections; 8 8 9 import org.junit.jupiter.api.Test; 9 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetSelector.PresetClassification;10 import org.openstreetmap.josm.testutils.JOSMTestRules;11 12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;13 10 14 11 /** … … 16 13 */ 17 14 class TaggingPresetSelectorTest { 18 19 15 /** 20 * Setup rule 21 */ 22 @RegisterExtension 23 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 24 public JOSMTestRules test = new JOSMTestRules(); 25 26 /** 27 * Unit test for {@link PresetClassification#isMatching}. 16 * Unit test for {@link TaggingPresetSelector.PresetClassifications#getMatchingPresets}. 28 17 */ 29 18 @Test 30 void test IsMatching() {19 void testGetMatching() { 31 20 TaggingPreset preset = new TaggingPreset(); 32 21 preset.name = "estação de bombeiros"; // fire_station in brazilian portuguese 33 PresetClassification pc = new PresetClassification(preset); 34 assertEquals(0, pc.isMatchingName("foo")); 35 assertTrue(pc.isMatchingName("estação") > 0); 36 assertTrue(pc.isMatchingName("estacao") > 0); 22 TaggingPresetSelector.PresetClassifications presetClassifications = new TaggingPresetSelector.PresetClassifications(); 23 presetClassifications.loadPresets(Collections.singleton(preset)); 24 assertTrue(presetClassifications.getMatchingPresets(null, new String[] {"foo"}, false, 25 false, null, null).isEmpty()); 26 assertSame(preset, presetClassifications.getMatchingPresets(null, new String[] {"estação"}, false, 27 false, null, null).get(0).preset); 28 assertSame(preset, presetClassifications.getMatchingPresets(null, new String[] {"estacao"}, false, 29 false, null, null).get(0).preset); 37 30 } 38 31 }
Note:
See TracChangeset
for help on using the changeset viewer.