Changeset 12464 in josm


Ignore:
Timestamp:
2017-07-10T23:12:16+02:00 (2 weeks ago)
Author:
michael2402
Message:

Apply #14923: Adjust the search dialog to allow to search for primitives that use a preset. Patch by bafonins

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java

    r12346 r12464  
    3636import javax.swing.JPanel;
    3737import javax.swing.JRadioButton;
     38import javax.swing.SwingUtilities;
    3839import javax.swing.text.BadLocationException;
     40import javax.swing.text.Document;
    3941import javax.swing.text.JTextComponent;
    4042
     
    5557import org.openstreetmap.josm.gui.preferences.ToolbarPreferences.ActionParser;
    5658import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     59import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
     60import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetSelector;
    5761import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
    5862import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
     
    232236                    @Override
    233237                    public void mouseClicked(MouseEvent e) {
    234                         try {
    235                             JTextComponent tf = hcb.getEditorComponent();
    236                             tf.getDocument().insertString(tf.getCaretPosition(), ' ' + insertText, null);
    237                         } catch (BadLocationException ex) {
    238                             throw new JosmRuntimeException(ex.getMessage(), ex);
     238                        JTextComponent tf = hcb.getEditorComponent();
     239
     240                        /*
     241                         * Make sure that the focus is transferred to the search text field
     242                         * from the selector component.
     243                         */
     244                        if (!tf.hasFocus()) {
     245                            tf.requestFocusInWindow();
    239246                        }
     247
     248                        /*
     249                         * In order to make interaction with the search dialog simpler,
     250                         * we make sure that if autocompletion triggers and the text field is
     251                         * not in focus, the correct area is selected. We first request focus
     252                         * and then execute the selection logic. invokeLater allows us to
     253                         * defer the selection until waiting for focus.
     254                         */
     255                        SwingUtilities.invokeLater(() -> {
     256                            try {
     257                                tf.getDocument().insertString(tf.getCaretPosition(), ' ' + insertText, null);
     258                            } catch (BadLocationException ex) {
     259                                throw new JosmRuntimeException(ex.getMessage(), ex);
     260                            }
     261                        });
    240262                    }
    241263                });
     
    245267    }
    246268
     269    /**
     270     * Builds and shows the search dialog.
     271     * @param initialValues A set of initial values needed in order to initialize the search dialog.
     272     *                      If is {@code null}, then default settings are used.
     273     * @return Returns {@link SearchAction} object containing parameters of the search.
     274     */
    247275    public static SearchSetting showSearchDialog(SearchSetting initialValues) {
    248276        if (initialValues == null) {
    249277            initialValues = new SearchSetting();
    250278        }
    251         // -- prepare the combo box with the search expressions
    252         //
     279
     280        // prepare the combo box with the search expressions
    253281        JLabel label = new JLabel(initialValues instanceof Filter ? tr("Filter string:") : tr("Search string:"));
    254         final HistoryComboBox hcbSearchString = new HistoryComboBox();
    255         final String tooltip = tr("Enter the search expression");
     282        HistoryComboBox hcbSearchString = new HistoryComboBox();
     283        String tooltip = tr("Enter the search expression");
    256284        hcbSearchString.setText(initialValues.text);
    257285        hcbSearchString.setToolTipText(tooltip);
     286
    258287        // we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
    259         //
    260288        List<String> searchExpressionHistory = getSearchExpressionHistory();
    261289        Collections.reverse(searchExpressionHistory);
     
    274302        bg.add(inSelection);
    275303
    276         final JCheckBox caseSensitive = new JCheckBox(tr("case sensitive"), initialValues.caseSensitive);
     304        JCheckBox caseSensitive = new JCheckBox(tr("case sensitive"), initialValues.caseSensitive);
    277305        JCheckBox allElements = new JCheckBox(tr("all objects"), initialValues.allElements);
    278306        allElements.setToolTipText(tr("Also include incomplete and deleted objects in search."));
    279307        JCheckBox addOnToolbar = new JCheckBox(tr("add toolbar button"), false);
    280308
    281         final JRadioButton standardSearch = new JRadioButton(tr("standard"), !initialValues.regexSearch && !initialValues.mapCSSSearch);
    282         final JRadioButton regexSearch = new JRadioButton(tr("regular expression"), initialValues.regexSearch);
    283         final JRadioButton mapCSSSearch = new JRadioButton(tr("MapCSS selector"), initialValues.mapCSSSearch);
    284         final ButtonGroup bg2 = new ButtonGroup();
     309        JRadioButton standardSearch = new JRadioButton(tr("standard"), !initialValues.regexSearch && !initialValues.mapCSSSearch);
     310        JRadioButton regexSearch = new JRadioButton(tr("regular expression"), initialValues.regexSearch);
     311        JRadioButton mapCSSSearch = new JRadioButton(tr("MapCSS selector"), initialValues.mapCSSSearch);
     312        ButtonGroup bg2 = new ButtonGroup();
    285313        bg2.add(standardSearch);
    286314        bg2.add(regexSearch);
    287315        bg2.add(mapCSSSearch);
    288 
    289         JPanel left = new JPanel(new GridBagLayout());
    290316
    291317        JPanel selectionSettings = new JPanel(new GridBagLayout());
     
    300326        additionalSettings.add(caseSensitive, GBC.eol().anchor(GBC.WEST).fill(GBC.HORIZONTAL));
    301327
     328        JPanel left = new JPanel(new GridBagLayout());
     329
    302330        left.add(selectionSettings, GBC.eol().fill(GBC.BOTH));
    303331        left.add(additionalSettings, GBC.eol().fill(GBC.BOTH));
     
    316344        }
    317345
    318         final JPanel right = SearchAction.buildHintsSection(hcbSearchString);
    319         final JPanel top = new JPanel(new GridBagLayout());
     346        JPanel right = SearchAction.buildHintsSection(hcbSearchString);
     347        JPanel top = new JPanel(new GridBagLayout());
    320348        top.add(label, GBC.std().insets(0, 0, 5, 0));
    321349        top.add(hcbSearchString, GBC.eol().fill(GBC.HORIZONTAL));
    322350
    323         final JTextComponent editorComponent = hcbSearchString.getEditorComponent();
    324         editorComponent.getDocument().addDocumentListener(new AbstractTextComponentValidator(editorComponent) {
     351        JTextComponent editorComponent = hcbSearchString.getEditorComponent();
     352        Document document = editorComponent.getDocument();
     353
     354        /*
     355         * Setup the logic to validate the contents of the search text field which is executed
     356         * every time the content of the field has changed. If the query is incorrect, then
     357         * the text field is colored red.
     358         */
     359        document.addDocumentListener(new AbstractTextComponentValidator(editorComponent) {
    325360
    326361            @Override
     
    349384        });
    350385
    351         final JPanel p = new JPanel(new GridBagLayout());
     386        /*
     387         * Setup the logic to append preset queries to the search text field according to
     388         * selected preset by the user. Every query is of the form ' group/sub-group/.../presetName'
     389         * if the corresponding group of the preset exists, otherwise it is simply ' presetName'.
     390         */
     391        TaggingPresetSelector selector = new TaggingPresetSelector(false, false);
     392        selector.setBorder(BorderFactory.createTitledBorder(tr("Search by preset")));
     393        selector.setDblClickListener(ev -> setPresetDblClickListener(selector, editorComponent));
     394
     395        JPanel p = new JPanel(new GridBagLayout());
    352396        p.add(top, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 5, 0));
    353397        p.add(left, GBC.std().anchor(GBC.NORTH).insets(5, 10, 10, 0).fill(GBC.VERTICAL));
    354         p.add(right, GBC.eol().fill(GBC.BOTH).insets(0, 10, 0, 0));
     398        p.add(right, GBC.std().fill(GBC.BOTH).insets(0, 10, 0, 0));
     399        p.add(selector, GBC.eol().fill(GBC.BOTH).insets(0, 10, 0, 0));
    355400
    356401        ExtendedDialog dialog = new ExtendedDialog(
     
    391436
    392437        // User pressed OK - let's perform the search
    393         SearchMode mode = replace.isSelected() ? SearchAction.SearchMode.replace
    394                 : (add.isSelected() ? SearchAction.SearchMode.add
    395                         : (remove.isSelected() ? SearchAction.SearchMode.remove : SearchAction.SearchMode.in_selection));
    396438        initialValues.text = hcbSearchString.getText();
    397         initialValues.mode = mode;
    398439        initialValues.caseSensitive = caseSensitive.isSelected();
    399440        initialValues.allElements = allElements.isSelected();
    400441        initialValues.regexSearch = regexSearch.isSelected();
    401442        initialValues.mapCSSSearch = mapCSSSearch.isSelected();
     443
     444        if (inSelection.isSelected()) {
     445            initialValues.mode = SearchAction.SearchMode.in_selection;
     446        } else if (replace.isSelected()) {
     447            initialValues.mode = SearchAction.SearchMode.replace;
     448        } else if (add.isSelected()) {
     449            initialValues.mode = SearchAction.SearchMode.add;
     450        } else {
     451            initialValues.mode = SearchAction.SearchMode.remove;
     452        }
    402453
    403454        if (addOnToolbar.isSelected()) {
     
    414465            Main.toolbar.addCustomButton(res, -1, false);
    415466        }
     467
    416468        return initialValues;
    417469    }
     
    458510                .addKeyword("untagged", "untagged ", tr("object without useful tags")),
    459511                GBC.eol());
     512            hintPanel.add(new SearchKeywordRow(hcbSearchString)
     513                    .addKeyword("preset:\"Annotation/Address\"", "preset:\"Annotation/Address\"",
     514                            tr("all objects that use the address preset"))
     515                    .addKeyword("preset:\"Geography/Nature/*\"", "preset:\"Geography/Nature/*\"",
     516                            tr("all objects that use any preset under the Geography/Nature group")),
     517                    GBC.eol().anchor(GBC.CENTER));
    460518            hintPanel.add(new SearchKeywordRow(hcbSearchString)
    461519                .addTitle(tr("metadata"))
     
    576634
    577635    /**
     636     *
     637     * @param selector Selector component that the user interacts with
     638     * @param searchEditor Editor for search queries
     639     */
     640    private static void setPresetDblClickListener(TaggingPresetSelector selector, JTextComponent searchEditor) {
     641        TaggingPreset selectedPreset = selector.getSelectedPresetAndUpdateClassification();
     642
     643        if (selectedPreset == null) {
     644            return;
     645        }
     646
     647        /*
     648         * Make sure that the focus is transferred to the search text field
     649         * from the selector component.
     650         */
     651        searchEditor.requestFocusInWindow();
     652
     653        /*
     654         * In order to make interaction with the search dialog simpler,
     655         * we make sure that if autocompletion triggers and the text field is
     656         * not in focus, the correct area is selected. We first request focus
     657         * and then execute the selection logic. invokeLater allows us to
     658         * defer the selection until waiting for focus.
     659         */
     660        SwingUtilities.invokeLater(() -> {
     661            int textOffset = searchEditor.getCaretPosition();
     662            String presetSearchQuery = " preset:" +
     663                    "\"" + selectedPreset.getRawName() + "\"";
     664            try {
     665                searchEditor.getDocument().insertString(textOffset, presetSearchQuery, null);
     666            } catch (BadLocationException e1) {
     667                throw new JosmRuntimeException(e1.getMessage(), e1);
     668            }
     669        });
     670    }
     671
     672    /**
    578673     * Interfaces implementing this may receive the result of the current search.
    579674     * @author Michael Zangl
     
    750845    }
    751846
     847    /**
     848     * This class defines a set of parameters that is used to
     849     * perform search within the search dialog.
     850     */
    752851    public static class SearchSetting {
    753852        public String text;
     
    811910        }
    812911
     912        /**
     913         * <p>Transforms a string following a certain format, namely "[R | A | D | S][C?,R?,A?,M?] [a-zA-Z]"
     914         * where the first part defines the mode of the search, see {@link SearchMode}, the second defines
     915         * a set of attributes within the {@code SearchSetting} class and the second is the search query.
     916         * <p>
     917         * Attributes are as follows:
     918         * <ul>
     919         *     <li>C - if search is case sensitive
     920         *     <li>R - if the regex syntax is used
     921         *     <li>A - if all objects are considered
     922         *     <li>M - if the mapCSS syntax is used
     923         * </ul>
     924         * <p>For example, "RC type:node" is a valid string representation of an object that replaces the
     925         * current selection, is case sensitive and searches for all objects of type node.
     926         * @param s A string representation of a {@code SearchSetting} object
     927         *          from which the object must be built.
     928         * @return A {@code SearchSetting} defined by the input string.
     929         */
    813930        public static SearchSetting readFromString(String s) {
    814931            if (s.isEmpty())
     
    852969        }
    853970
     971        /**
     972         * Builds a string representation of the {@code SearchSetting} object,
     973         * see {@link #readFromString(String)} for more details.
     974         * @return A string representation of the {@code SearchSetting} object.
     975         */
    854976        public String writeToString() {
    855977            if (text == null || text.isEmpty())
  • trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java

    r11978 r12464  
    2121import java.util.regex.Pattern;
    2222import java.util.regex.PatternSyntaxException;
     23import java.util.stream.Collectors;
    2324
    2425import org.openstreetmap.josm.Main;
     
    3940import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser;
    4041import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.ParseException;
     42import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
     43import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetMenu;
     44import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetSeparator;
     45import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
    4146import org.openstreetmap.josm.tools.AlphanumComparator;
    4247import org.openstreetmap.josm.tools.Geometry;
     
    116121                "changeset", "nodes", "ways", "tags", "areasize", "waylength", "modified", "deleted", "selected",
    117122                "incomplete", "untagged", "closed", "new", "indownloadedarea",
    118                 "allindownloadedarea", "inview", "allinview", "timestamp", "nth", "nth%", "hasRole");
     123                "allindownloadedarea", "inview", "allinview", "timestamp", "nth", "nth%", "hasRole", "preset");
    119124
    120125        @Override
     
    152157                    case "type":
    153158                        return new ExactType(tokenizer.readTextOrNumber());
     159                    case "preset":
     160                        return new Preset(tokenizer.readTextOrNumber());
    154161                    case "user":
    155162                        return new UserMatch(tokenizer.readTextOrNumber());
     
    15551562    }
    15561563
     1564    /**
     1565     * Matches presets.
     1566     * @since 12464
     1567     */
     1568    private static class Preset extends Match {
     1569        private final List<TaggingPreset> presets;
     1570
     1571        Preset(String presetName) throws ParseError {
     1572
     1573            if (presetName == null || presetName.equals("")) {
     1574                throw new ParseError("The name of the preset is required");
     1575            }
     1576
     1577            int wildCardIdx = presetName.lastIndexOf("*");
     1578            int length = presetName.length() - 1;
     1579
     1580            /*
     1581             * Match strictly (simply comparing the names) if there is no '*' symbol
     1582             * at the end of the name or '*' is a part of the preset name.
     1583             */
     1584            boolean matchStrictly = wildCardIdx == -1 || wildCardIdx != length;
     1585
     1586            this.presets = TaggingPresets.getTaggingPresets()
     1587                    .stream()
     1588                    .filter(preset -> !(preset instanceof TaggingPresetMenu || preset instanceof TaggingPresetSeparator))
     1589                    .filter(preset -> this.presetNameMatch(presetName, preset, matchStrictly))
     1590                    .collect(Collectors.toList());
     1591
     1592            if (this.presets.isEmpty()) {
     1593                throw new ParseError(tr("Unknown preset name: ") + presetName);
     1594            }
     1595        }
     1596
     1597        @Override
     1598        public boolean match(OsmPrimitive osm) {
     1599            for (TaggingPreset preset : this.presets) {
     1600                if (preset.test(osm)) {
     1601                    return true;
     1602                }
     1603            }
     1604
     1605            return false;
     1606        }
     1607
     1608        private boolean presetNameMatch(String name, TaggingPreset preset, boolean matchStrictly) {
     1609            if (matchStrictly) {
     1610                return name.equalsIgnoreCase(preset.getRawName());
     1611            }
     1612
     1613            try {
     1614                String groupSuffix = name.substring(0, name.length() - 2); // try to remove '/*'
     1615                TaggingPresetMenu group = preset.group;
     1616
     1617                return group != null && groupSuffix.equalsIgnoreCase(group.getRawName());
     1618            } catch (StringIndexOutOfBoundsException ex) {
     1619                return false;
     1620            }
     1621        }
     1622    }
     1623
    15571624    public static class ParseError extends Exception {
    15581625        public ParseError(String msg) {
     
    18051872    }
    18061873}
     1874
  • trunk/test/unit/org/openstreetmap/josm/actions/search/SearchCompilerTest.java

    r11978 r12464  
    88import static org.junit.Assert.fail;
    99
     10import java.lang.reflect.Field;
    1011import java.nio.charset.StandardCharsets;
    1112import java.nio.file.Files;
    1213import java.nio.file.Paths;
     14import java.util.Arrays;
     15import java.util.Collection;
     16import java.util.Collections;
    1317
    1418import org.junit.Rule;
     
    3135import org.openstreetmap.josm.data.osm.Way;
    3236import org.openstreetmap.josm.data.osm.WayData;
     37import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
     38import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetType;
     39import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
     40import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetMenu;
     41import org.openstreetmap.josm.gui.tagging.presets.items.Key;
    3342import org.openstreetmap.josm.testutils.JOSMTestRules;
    3443import org.openstreetmap.josm.tools.date.DateUtils;
     
    491500        TestUtils.superficialEnumCodeCoverage(ExactKeyValue.Mode.class);
    492501    }
     502
     503    /**
     504     * Robustness test for preset searching. Ensures that the query 'preset:' is not accepted.
     505     * @throws ParseError always
     506     * @since 12464
     507     */
     508    @Test(expected = ParseError.class)
     509    public void testPresetSearchMissingValue() throws ParseError {
     510        SearchSetting settings = new SearchSetting();
     511        settings.text = "preset:";
     512        settings.mapCSSSearch = false;
     513
     514        TaggingPresets.readFromPreferences();
     515
     516        SearchCompiler.compile(settings);
     517    }
     518
     519    /**
     520     * Robustness test for preset searching. Validates that it is not possible to search for
     521     * non existing presets.
     522     * @throws ParseError always
     523     * @since 12464
     524     */
     525    @Test(expected = ParseError.class)
     526    public void testPresetNotExist() throws ParseError {
     527        String testPresetName = "groupnamethatshouldnotexist/namethatshouldnotexist";
     528        SearchSetting settings = new SearchSetting();
     529        settings.text = "preset:" + testPresetName;
     530        settings.mapCSSSearch = false;
     531
     532        // load presets
     533        TaggingPresets.readFromPreferences();
     534
     535        SearchCompiler.compile(settings);
     536    }
     537
     538    /**
     539     * Robustness tests for preset searching. Ensures that combined preset names (having more than
     540     * 1 word) must be enclosed with " .
     541     * @throws ParseError always
     542     * @since 12464
     543     */
     544    @Test(expected = ParseError.class)
     545    public void testPresetMultipleWords() throws ParseError {
     546        TaggingPreset testPreset = new TaggingPreset();
     547        testPreset.name = "Test Combined Preset Name";
     548        testPreset.group = new TaggingPresetMenu();
     549        testPreset.group.name = "TestGroupName";
     550
     551        String combinedPresetname = testPreset.getRawName();
     552        SearchSetting settings = new SearchSetting();
     553        settings.text = "preset:" + combinedPresetname;
     554        settings.mapCSSSearch = false;
     555
     556        // load presets
     557        TaggingPresets.readFromPreferences();
     558
     559        SearchCompiler.compile(settings);
     560    }
     561
     562
     563    /**
     564     * Ensures that correct presets are stored in the {@link org.openstreetmap.josm.actions.search.SearchCompiler.Preset}
     565     * class against which the osm primitives are tested.
     566     * @throws ParseError if an error has been encountered while compiling
     567     * @throws NoSuchFieldException if there is no field called 'presets'
     568     * @throws IllegalAccessException if cannot access the field where all matching presets are stored
     569     * @since 12464
     570     */
     571    @Test
     572    public void testPresetLookup() throws ParseError, NoSuchFieldException, IllegalAccessException {
     573        TaggingPreset testPreset = new TaggingPreset();
     574        testPreset.name = "Test Preset Name";
     575        testPreset.group = new TaggingPresetMenu();
     576        testPreset.group.name = "Test Preset Group Name";
     577
     578        String query = "preset:" +
     579                "\"" + testPreset.getRawName() + "\"";
     580        SearchSetting settings = new SearchSetting();
     581        settings.text = query;
     582        settings.mapCSSSearch = false;
     583
     584        // load presets and add the test preset
     585        TaggingPresets.readFromPreferences();
     586        TaggingPresets.addTaggingPresets(Collections.singletonList(testPreset));
     587
     588        Match match = SearchCompiler.compile(settings);
     589
     590        // access the private field where all matching presets are stored
     591        // and ensure that indeed the correct ones are there
     592        Field field = match.getClass().getDeclaredField("presets");
     593        field.setAccessible(true);
     594        Collection<TaggingPreset> foundPresets = (Collection<TaggingPreset>) field.get(match);
     595
     596        assertEquals(1, foundPresets.size());
     597        assertTrue(foundPresets.contains(testPreset));
     598    }
     599
     600    /**
     601     * Ensures that the wildcard search works and that correct presets are stored in
     602     * the {@link org.openstreetmap.josm.actions.search.SearchCompiler.Preset} class against which
     603     * the osm primitives are tested.
     604     * @throws ParseError if an error has been encountered while compiling
     605     * @throws NoSuchFieldException if there is no field called 'presets'
     606     * @throws IllegalAccessException if cannot access the field where all matching presets are stored
     607     * @since 12464
     608     */
     609    @Test
     610    public void testPresetLookupWildcard() throws ParseError, NoSuchFieldException, IllegalAccessException {
     611        TaggingPresetMenu group = new TaggingPresetMenu();
     612        group.name = "TestPresetGroup";
     613
     614        TaggingPreset testPreset1 = new TaggingPreset();
     615        testPreset1.name = "TestPreset1";
     616        testPreset1.group = group;
     617
     618        TaggingPreset testPreset2 = new TaggingPreset();
     619        testPreset2.name = "TestPreset2";
     620        testPreset2.group = group;
     621
     622        TaggingPreset testPreset3 = new TaggingPreset();
     623        testPreset3.name = "TestPreset3";
     624        testPreset3.group = group;
     625
     626        String query = "preset:" + "\"" + group.getRawName() + "/*\"";
     627        SearchSetting settings = new SearchSetting();
     628        settings.text = query;
     629        settings.mapCSSSearch = false;
     630
     631        TaggingPresets.readFromPreferences();
     632        TaggingPresets.addTaggingPresets(Arrays.asList(testPreset1, testPreset2, testPreset3));
     633
     634        Match match = SearchCompiler.compile(settings);
     635
     636        // access the private field where all matching presets are stored
     637        // and ensure that indeed the correct ones are there
     638        Field field = match.getClass().getDeclaredField("presets");
     639        field.setAccessible(true);
     640        Collection<TaggingPreset> foundPresets = (Collection<TaggingPreset>) field.get(match);
     641
     642        assertEquals(3, foundPresets.size());
     643        assertTrue(foundPresets.contains(testPreset1));
     644        assertTrue(foundPresets.contains(testPreset2));
     645        assertTrue(foundPresets.contains(testPreset3));
     646    }
     647
     648    /**
     649     * Ensures that correct primitives are matched against the specified preset.
     650     * @throws ParseError if an error has been encountered while compiling
     651     * @since 12464
     652     */
     653    @Test
     654    public void testPreset() throws ParseError {
     655        final String presetName = "Test Preset Name";
     656        final String presetGroupName = "Test Preset Group";
     657        final String key = "test_key1";
     658        final String val = "test_val1";
     659
     660        Key key1 = new Key();
     661        key1.key = key;
     662        key1.value = val;
     663
     664        TaggingPreset testPreset = new TaggingPreset();
     665        testPreset.name = presetName;
     666        testPreset.types = Collections.singleton(TaggingPresetType.NODE);
     667        testPreset.data.add(key1);
     668        testPreset.group = new TaggingPresetMenu();
     669        testPreset.group.name = presetGroupName;
     670
     671        TaggingPresets.readFromPreferences();
     672        TaggingPresets.addTaggingPresets(Collections.singleton(testPreset));
     673
     674        String query = "preset:" + "\"" + testPreset.getRawName() + "\"";
     675
     676        SearchContext ctx = new SearchContext(query);
     677        ctx.n1.put(key, val);
     678        ctx.n2.put(key, val);
     679
     680        for (OsmPrimitive osm : new OsmPrimitive[] {ctx.n1, ctx.n2}) {
     681            ctx.match(osm, true);
     682        }
     683
     684        for (OsmPrimitive osm : new OsmPrimitive[] {ctx.r1, ctx.r2, ctx.w1, ctx.w2}) {
     685            ctx.match(osm, false);
     686        }
     687    }
    493688}
     689
Note: See TracChangeset for help on using the changeset viewer.