Ticket #9463: 0001-see-9463-Refactoring.patch

File 0001-see-9463-Refactoring.patch, 14.6 KB (added by simon04, 10 years ago)
  • src/org/openstreetmap/josm/actions/search/SearchCompiler.java

    From 776bcbbbda1132ae95d6a061dfc807972653baae Mon Sep 17 00:00:00 2001
    From: Simon Legner <Simon.Legner@gmail.com>
    Date: Sun, 18 Oct 2015 20:17:06 +0200
    Subject: [PATCH 1/2] see #9463 - Refactoring
    
    * Refactor `SearchCompiler` to work with `Tagged` instances
    * Extract `CompileSearchTextDecorator` from `RelationListDialog`
    ---
     .../josm/actions/search/SearchCompiler.java        | 83 +++++++++++++++++-----
     .../josm/gui/dialogs/RelationListDialog.java       | 37 ++--------
     .../gui/widgets/CompileSearchTextDecorator.java    | 74 +++++++++++++++++++
     3 files changed, 146 insertions(+), 48 deletions(-)
     create mode 100644 src/org/openstreetmap/josm/gui/widgets/CompileSearchTextDecorator.java
    
    diff --git a/src/org/openstreetmap/josm/actions/search/SearchCompiler.java b/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
    index fec4084..1a16c84 100644
    a b  
    2727import org.openstreetmap.josm.data.osm.OsmUtils;
    2828import org.openstreetmap.josm.data.osm.Relation;
    2929import org.openstreetmap.josm.data.osm.RelationMember;
     30import org.openstreetmap.josm.data.osm.Tagged;
    3031import org.openstreetmap.josm.data.osm.Way;
    3132import org.openstreetmap.josm.gui.mappaint.Environment;
    3233import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    else if ("child".equals(keyword))  
    232233    }
    233234
    234235    /**
    235      * Base class for all search operators.
     236     * Base class for all search criteria. If the criterion only depends on an object's tags,
     237     * inherit from {@link org.openstreetmap.josm.actions.search.SearchCompiler.TaggedMatch}.
    236238     */
    237239    public abstract static class Match implements Predicate<OsmPrimitive> {
    238240
     241        /**
     242         * Tests whether the primitive matches this criterion.
     243         * @param osm the primitive to test
     244         * @return true if the primitive matches this criterion
     245         */
    239246        public abstract boolean match(OsmPrimitive osm);
    240247
    241248        /**
     249         * Tests whether the tagged object matches this criterion.
     250         * @param tagged the tagged object to test
     251         * @return true if the tagged object matches this criterion
     252         */
     253        public boolean match(Tagged tagged) {
     254            return false;
     255        }
     256
     257        /**
    242258         * Tests whether one of the primitives matches.
    243259         */
    244260        protected boolean existsMatch(Collection<? extends OsmPrimitive> primitives) {
    public final boolean evaluate(OsmPrimitive object) {  
    266282        }
    267283    }
    268284
     285    public abstract static class TaggedMatch extends Match {
     286
     287        @Override
     288        public abstract boolean match(Tagged tags);
     289
     290        @Override
     291        public final boolean match(OsmPrimitive osm) {
     292            return match((Tagged) osm);
     293        }
     294    }
     295
    269296    /**
    270297     * A unary search operator which may take data parameters.
    271298     */
    public Match getRhs() {  
    313340    /**
    314341     * Matches every OsmPrimitive.
    315342     */
    316     public static class Always extends Match {
     343    public static class Always extends TaggedMatch {
    317344        /** The unique instance/ */
    318345        public static final Always INSTANCE = new Always();
    319346        @Override
    320         public boolean match(OsmPrimitive osm) {
     347        public boolean match(Tagged osm) {
    321348            return true;
    322349        }
    323350    }
    public boolean match(OsmPrimitive osm) {  
    325352    /**
    326353     * Never matches any OsmPrimitive.
    327354     */
    328     public static class Never extends Match {
     355    public static class Never extends TaggedMatch {
    329356        @Override
    330         public boolean match(OsmPrimitive osm) {
     357        public boolean match(Tagged osm) {
    331358            return false;
    332359        }
    333360    }
    public boolean match(OsmPrimitive osm) {  
    346373        }
    347374
    348375        @Override
     376        public boolean match(Tagged osm) {
     377            return !match.match(osm);
     378        }
     379
     380        @Override
    349381        public String toString() {
    350382            return "!" + match;
    351383        }
    public Match getMatch() {  
    358390    /**
    359391     * Matches if the value of the corresponding key is ''yes'', ''true'', ''1'' or ''on''.
    360392     */
    361     private static class BooleanMatch extends Match {
     393    private static class BooleanMatch extends TaggedMatch {
    362394        private final String key;
    363395        private final boolean defaultValue;
    364396
    public Match getMatch() {  
    368400        }
    369401
    370402        @Override
    371         public boolean match(OsmPrimitive osm) {
     403        public boolean match(Tagged osm) {
    372404            Boolean ret = OsmUtils.getOsmBoolean(osm.get(key));
    373405            if (ret == null)
    374406                return defaultValue;
    public boolean match(OsmPrimitive osm) {  
    396428        }
    397429
    398430        @Override
     431        public boolean match(Tagged osm) {
     432            return lhs.match(osm) && rhs.match(osm);
     433        }
     434
     435        @Override
    399436        public String toString() {
    400437            return lhs + " && " + rhs;
    401438        }
    public boolean match(OsmPrimitive osm) {  
    415452        }
    416453
    417454        @Override
     455        public boolean match(Tagged osm) {
     456            return lhs.match(osm) || rhs.match(osm);
     457        }
     458
     459        @Override
    418460        public String toString() {
    419461            return lhs + " || " + rhs;
    420462        }
    public boolean match(OsmPrimitive osm) {  
    434476        }
    435477
    436478        @Override
     479        public boolean match(Tagged osm) {
     480            return lhs.match(osm) ^ rhs.match(osm);
     481        }
     482
     483        @Override
    437484        public String toString() {
    438485            return lhs + " ^ " + rhs;
    439486        }
    protected String getString() {  
    511558    /**
    512559     * Matches objects with the given key-value pair.
    513560     */
    514     private static class KeyValue extends Match {
     561    private static class KeyValue extends TaggedMatch {
    515562        private final String key;
    516563        private final Pattern keyPattern;
    517564        private final String value;
    protected String getString() {  
    554601        }
    555602
    556603        @Override
    557         public boolean match(OsmPrimitive osm) {
     604        public boolean match(Tagged osm) {
    558605
    559606            if (keyPattern != null) {
    560607                if (!osm.hasKeys())
    public boolean match(OsmPrimitive osm) {  
    584631            } else {
    585632                String mv = null;
    586633
    587                 if ("timestamp".equals(key)) {
    588                     mv = DateUtils.fromTimestamp(osm.getRawTimestamp());
     634                if ("timestamp".equals(key) && osm instanceof OsmPrimitive) {
     635                    mv = DateUtils.fromTimestamp(((OsmPrimitive) osm).getRawTimestamp());
    589636                } else {
    590637                    mv = osm.get(key);
    591638                    if (!caseSensitive && mv == null) {
    public String toString() {  
    618665        }
    619666    }
    620667
    621     public static class ValueComparison extends Match {
     668    public static class ValueComparison extends TaggedMatch {
    622669        private final String key;
    623670        private final String referenceValue;
    624671        private final Double referenceNumber;
    public ValueComparison(String key, String referenceValue, int compareMode) {  
    641688        }
    642689
    643690        @Override
    644         public boolean match(OsmPrimitive osm) {
     691        public boolean match(Tagged osm) {
    645692            final String currentValue = osm.get(key);
    646693            final int compareResult;
    647694            if (currentValue == null) {
    public String toString() {  
    669716    /**
    670717     * Matches objects with the exact given key-value pair.
    671718     */
    672     public static class ExactKeyValue extends Match {
     719    public static class ExactKeyValue extends TaggedMatch {
    673720
    674721        private enum Mode {
    675722            ANY, ANY_KEY, ANY_VALUE, EXACT, NONE, MISSING_KEY,
    public ExactKeyValue(boolean regexp, String key, String value) throws ParseError  
    742789        }
    743790
    744791        @Override
    745         public boolean match(OsmPrimitive osm) {
     792        public boolean match(Tagged osm) {
    746793
    747794            if (!osm.hasKeys())
    748795                return mode == Mode.NONE;
    public String toString() {  
    799846    /**
    800847     * Match a string in any tags (key or value), with optional regex and case insensitivity.
    801848     */
    802     private static class Any extends Match {
     849    private static class Any extends TaggedMatch {
    803850        private final String search;
    804851        private final Pattern searchRegex;
    805852        private final boolean caseSensitive;
    public String toString() {  
    826873        }
    827874
    828875        @Override
    829         public boolean match(OsmPrimitive osm) {
    830             if (!osm.hasKeys() && osm.getUser() == null)
     876        public boolean match(Tagged osm) {
     877            if (!osm.hasKeys())
    831878                return search.isEmpty();
    832879
    833880            for (String key: osm.keySet()) {
  • src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java b/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
    index a299979..7de01ca 100644
    a b  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    66import java.awt.BorderLayout;
    7 import java.awt.Color;
    87import java.awt.Component;
    98import java.awt.event.ActionEvent;
    109import java.awt.event.KeyEvent;
    1110import java.awt.event.MouseEvent;
     11import java.beans.PropertyChangeEvent;
     12import java.beans.PropertyChangeListener;
    1213import java.util.ArrayList;
    1314import java.util.Arrays;
    1415import java.util.Collection;
     
    2829import javax.swing.JScrollPane;
    2930import javax.swing.KeyStroke;
    3031import javax.swing.ListSelectionModel;
    31 import javax.swing.UIManager;
    32 import javax.swing.event.DocumentEvent;
    33 import javax.swing.event.DocumentListener;
    3432import javax.swing.event.ListSelectionEvent;
    3533import javax.swing.event.ListSelectionListener;
    3634
     
    6967import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    7068import org.openstreetmap.josm.gui.util.GuiHelper;
    7169import org.openstreetmap.josm.gui.util.HighlightHelper;
     70import org.openstreetmap.josm.gui.widgets.CompileSearchTextDecorator;
    7271import org.openstreetmap.josm.gui.widgets.DisableShortcutsOnFocusGainedTextField;
    7372import org.openstreetmap.josm.gui.widgets.JosmTextField;
    7473import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
    public void selectRelations(Collection<Relation> relations) {  
    282281    private JosmTextField  setupFilter() {
    283282        final JosmTextField f = new DisableShortcutsOnFocusGainedTextField();
    284283        f.setToolTipText(tr("Relation list filter"));
    285         f.getDocument().addDocumentListener(new DocumentListener() {
    286 
    287             private void setFilter() {
    288                 try {
    289                     f.setBackground(UIManager.getColor("TextField.background"));
    290                     f.setToolTipText(tr("Relation list filter"));
    291                     model.setFilter(SearchCompiler.compile(filter.getText()));
    292                 } catch (SearchCompiler.ParseError ex) {
    293                     f.setBackground(new Color(255, 224, 224));
    294                     f.setToolTipText(ex.getMessage());
    295                     model.setFilter(new SearchCompiler.Always());
    296                 }
    297             }
    298 
    299             @Override
    300             public void insertUpdate(DocumentEvent e) {
    301                 setFilter();
    302             }
    303 
    304             @Override
    305             public void removeUpdate(DocumentEvent e) {
    306                 setFilter();
    307             }
    308 
     284        final CompileSearchTextDecorator decorator = CompileSearchTextDecorator.decorate(f);
     285        f.addPropertyChangeListener("filter", new PropertyChangeListener() {
    309286            @Override
    310             public void changedUpdate(DocumentEvent e) {
    311                 setFilter();
     287            public void propertyChange(PropertyChangeEvent evt) {
     288                model.setFilter(decorator.getMatch());
    312289            }
    313290        });
    314291        return f;
  • new file src/org/openstreetmap/josm/gui/widgets/CompileSearchTextDecorator.java

    diff --git a/src/org/openstreetmap/josm/gui/widgets/CompileSearchTextDecorator.java b/src/org/openstreetmap/josm/gui/widgets/CompileSearchTextDecorator.java
    new file mode 100644
    index 0000000..bf0c70a
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.widgets;
     3
     4import java.awt.Color;
     5
     6import javax.swing.UIManager;
     7import javax.swing.event.DocumentEvent;
     8import javax.swing.event.DocumentListener;
     9import javax.swing.text.JTextComponent;
     10
     11import org.openstreetmap.josm.actions.search.SearchCompiler;
     12
     13/**
     14 * Decorates a text component with an execution to the search compiler. Afterwards, a {@code "filter"} property change
     15 * will be fired and the compiled search can be accessed with {@link #getMatch()}.
     16 */
     17public class CompileSearchTextDecorator implements DocumentListener {
     18
     19    private final JTextComponent textComponent;
     20    private final String originalToolTipText;
     21    private SearchCompiler.Match filter = null;
     22
     23    private CompileSearchTextDecorator(JTextComponent textComponent) {
     24        this.textComponent = textComponent;
     25        this.originalToolTipText = textComponent.getToolTipText();
     26        textComponent.getDocument().addDocumentListener(this);
     27    }
     28
     29    /**
     30     * Decorates a text component with an execution to the search compiler. Afterwards, a {@code "filter"} property change
     31     * will be fired and the compiled search can be accessed with {@link #getMatch()}.
     32     * @param f the text component to decorate
     33     * @return an instance of the decorator in order to access the compiled search via {@link #getMatch()}
     34     */
     35    public static CompileSearchTextDecorator decorate(JTextComponent f) {
     36        return new CompileSearchTextDecorator(f);
     37    }
     38
     39    private void setFilter() {
     40        try {
     41            textComponent.setBackground(UIManager.getColor("TextField.background"));
     42            textComponent.setToolTipText(originalToolTipText);
     43            filter = SearchCompiler.compile(textComponent.getText());
     44        } catch (SearchCompiler.ParseError ex) {
     45            textComponent.setBackground(new Color(255, 224, 224));
     46            textComponent.setToolTipText(ex.getMessage());
     47            filter = new SearchCompiler.Always();
     48        }
     49        textComponent.firePropertyChange("filter", 0, 1);
     50    }
     51
     52    /**
     53     * Returns the compiled search
     54     * @return the compiled search
     55     */
     56    public SearchCompiler.Match getMatch() {
     57        return filter;
     58    }
     59
     60    @Override
     61    public void insertUpdate(DocumentEvent e) {
     62        setFilter();
     63    }
     64
     65    @Override
     66    public void removeUpdate(DocumentEvent e) {
     67        setFilter();
     68    }
     69
     70    @Override
     71    public void changedUpdate(DocumentEvent e) {
     72        setFilter();
     73    }
     74}