Ticket #5933: 5933.patch

File 5933.patch, 28.3 KB (added by simon04, 8 years ago)
  • src/org/openstreetmap/josm/gui/dialogs/properties/PresetListPanel.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/properties/PresetListPanel.java b/src/org/openstreetmap/josm/gui/dialogs/properties/PresetListPanel.java
    index 3c63305..fe03b79 100644
    a b import java.awt.event.MouseListener; 
    1010import java.awt.font.TextAttribute;
    1111import java.util.Collection;
    1212import java.util.Collections;
    13 import java.util.Hashtable;
    1413import java.util.List;
    1514import java.util.Map;
    1615
    import org.openstreetmap.josm.data.osm.OsmPrimitive; 
    2322import org.openstreetmap.josm.data.osm.Tag;
    2423import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference;
    2524import org.openstreetmap.josm.gui.tagging.TaggingPreset;
    26 import org.openstreetmap.josm.gui.tagging.TaggingPreset.Check;
    27 import org.openstreetmap.josm.gui.tagging.TaggingPreset.Combo;
    2825import org.openstreetmap.josm.gui.tagging.TaggingPreset.PresetType;
    29 import org.openstreetmap.josm.gui.tagging.TaggingPreset.Text;
    3026import org.openstreetmap.josm.tools.GBC;
    3127
    3228public class PresetListPanel extends JPanel {
    public class PresetListPanel extends JPanel { 
    8177        public void mouseReleased(MouseEvent arg0) {}
    8278    }
    8379
    84     public void updatePresets(int nodes, int ways, int relations, int closedways, Map<String, Map<String, Integer>> valueCount, PresetHandler presetHandler) {
     80    public void updatePresets(final Collection<PresetType> types, final Map<String, String> tags, PresetHandler presetHandler) {
    8581
    8682        removeAll();
    87         int total = nodes+ways+relations+closedways;
    88         if(total == 0) {
     83        if (types.isEmpty()) {
    8984            setVisible(false);
    9085            return;
    9186        }
    9287
    93         for(TaggingPreset t : TaggingPresetPreference.taggingPresets) {
    94             if(
    95                     (       t.types == null
    96                             || (relations > 0 && t.types.contains(PresetType.RELATION))
    97                             || (nodes > 0 && t.types.contains(PresetType.NODE))
    98                             || (ways+closedways > 0 && t.types.contains(PresetType.WAY))
    99                             || (closedways > 0 && t.types.contains(PresetType.CLOSEDWAY))
    100                     )
    101                     && t.isShowable())
    102             {
    103                 int found = 0;
    104                 for(TaggingPreset.Item i : t.data) {
    105                     if(i instanceof TaggingPreset.Key) {
    106                         String val = ((TaggingPreset.Key)i).value;
    107                         String key = ((TaggingPreset.Key)i).key;
    108                         // we subtract 100 if not found and add 1 if found
    109                         found -= 100;
    110                         if(key == null || !valueCount.containsKey(key)) {
    111                             continue;
    112                         }
    113 
    114                         Map<String, Integer> v = valueCount.get(key);
    115                         if(v.size() == 1 && val != null && v.containsKey(val) && v.get(val) == total) {
    116                             found += 101;
    117                         }
    118                     } else {
    119                         String key = null;
    120                         if ((i instanceof Text) && ((Text)i).required) {
    121                             key = ((Text)i).key;
    122                         } else if ((i instanceof Combo) && ((Combo)i).required) {
    123                             key = ((Combo)i).key;
    124                         } else if ((i instanceof Check) && ((Check)i).required) {
    125                             key = ((Check)i).key;
    126                         }
    127                         if (key != null) {
    128                             if (valueCount.get(key) != null) {
    129                                 found += 1;
    130                             } else {
    131                                 found -= 100;
    132                             }
    133                         }
    134                     }
    135                 }
    136 
    137                 if(found <= 0) {
    138                     continue;
    139                 }
    140 
    141                 JLabel lbl = new JLabel(t.getName() + " …");
    142                 lbl.setIcon((Icon) t.getValue(Action.SMALL_ICON));
    143                 lbl.addMouseListener(new PresetLabelML(lbl, t, presetHandler));
    144                 add(lbl, GBC.eol().fill(GBC.HORIZONTAL));
     88        for (TaggingPreset t : TaggingPresetPreference.taggingPresets) {
     89            if (!t.matches(types, tags)) {
     90                continue;
    14591            }
     92
     93            JLabel lbl = new JLabel(t.getName() + " …");
     94            lbl.setIcon((Icon) t.getValue(Action.SMALL_ICON));
     95            lbl.addMouseListener(new PresetLabelML(lbl, t, presetHandler));
     96            add(lbl, GBC.eol().fill(GBC.HORIZONTAL));
    14697        }
    14798
    148         if(getComponentCount() > 0) {
     99        if (getComponentCount() > 0) {
    149100            setVisible(true);
    150101            // This ensures the presets are exactly as high as needed.
    151102            int height = getComponentCount() * getComponent(0).getHeight();
    public class PresetListPanel extends JPanel { 
    156107            setVisible(false);
    157108        }
    158109    }
    159 
    160110}
  • src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java b/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
    index 15bcc62..f8edcfd 100644
    a b import java.util.Arrays; 
    3030import java.util.Collection;
    3131import java.util.Collections;
    3232import java.util.Comparator;
     33import java.util.EnumSet;
    3334import java.util.HashMap;
    3435import java.util.HashSet;
    3536import java.util.Iterator;
    import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask; 
    103104import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
    104105import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    105106import org.openstreetmap.josm.gui.tagging.TaggingPreset;
     107import org.openstreetmap.josm.gui.tagging.TaggingPreset.PresetType;
    106108import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox;
    107109import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
    108110import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
    public class PropertiesDialog extends ToggleDialog implements SelectionChangedLi 
    260262                Component c = super.getListCellRendererComponent(list, value,
    261263                        index, isSelected, cellHasFocus);
    262264                if (c instanceof JLabel) {
    263                     String str = null;
    264                     str=((AutoCompletionListItem) value).getValue();
    265                     if (valueCount.containsKey(objKey)){
    266                         Map<String, Integer> m=valueCount.get(objKey);
     265                    String str = ((AutoCompletionListItem) value).getValue();
     266                    if (valueCount.containsKey(objKey)) {
     267                        Map<String, Integer> m = valueCount.get(objKey);
    267268                        if (m.containsKey(str)) {
    268                             str+="("+m.get(str)+")";
    269                             c.setFont(c.getFont().deriveFont(Font.ITALIC+Font.BOLD));
     269                            str = tr("{0} ({1})", str, m.get(str));
     270                            c.setFont(c.getFont().deriveFont(Font.ITALIC + Font.BOLD));
    270271                        }
    271272                    }
    272                     ((JLabel)c).setText(str);
     273                    ((JLabel) c).setText(str);
    273274                }
    274275                return c;
    275276            }
    public class PropertiesDialog extends ToggleDialog implements SelectionChangedLi 
    946947
    947948        // re-load property data
    948949        propertyData.setRowCount(0);
    949         int nodes = 0;
    950         int ways = 0;
    951         int relations = 0;
    952         int closedways = 0;
    953950
    954         Map<String, Integer> keyCount = new HashMap<String, Integer>();
     951        final Map<String, Integer> keyCount = new HashMap<String, Integer>();
     952        final Map<String, String> tags = new HashMap<String, String>();
    955953        valueCount.clear();
     954        EnumSet<PresetType> types = EnumSet.noneOf(TaggingPreset.PresetType.class);
    956955        for (OsmPrimitive osm : newSelection) {
    957             if(osm instanceof Node) {
    958                 ++nodes;
    959             } else if(osm instanceof Relation) {
    960                 ++relations;
    961             } else if(((Way)osm).isClosed()) {
    962                 ++closedways;
    963             } else {
    964                 ++ways;
    965             }
    966             for (String key: osm.keySet()) {
     956            types.add(PresetType.forPrimitive(osm));
     957            for (String key : osm.keySet()) {
    967958                String value = osm.get(key);
    968959                keyCount.put(key, keyCount.containsKey(key) ? keyCount.get(key) + 1 : 1);
    969960                if (valueCount.containsKey(key)) {
    970961                    Map<String, Integer> v = valueCount.get(key);
    971                     v.put(value, v.containsKey(value)? v.get(value) + 1 : 1 );
     962                    v.put(value, v.containsKey(value) ? v.get(value) + 1 : 1);
    972963                } else {
    973                     TreeMap<String,Integer> v = new TreeMap<String, Integer>();
     964                    TreeMap<String, Integer> v = new TreeMap<String, Integer>();
    974965                    v.put(value, 1);
    975966                    valueCount.put(key, v);
    976967                }
    977968            }
    978969        }
    979970        for (Entry<String, Map<String, Integer>> e : valueCount.entrySet()) {
    980             int count=0;
    981             for (Entry<String, Integer> e1: e.getValue().entrySet()) {
    982                 count+=e1.getValue();
     971            int count = 0;
     972            for (Entry<String, Integer> e1 : e.getValue().entrySet()) {
     973                count += e1.getValue();
    983974            }
    984975            if (count < newSelection.size()) {
    985                 e.getValue().put("", newSelection.size()-count);
     976                e.getValue().put("", newSelection.size() - count);
    986977            }
    987978            propertyData.addRow(new Object[]{e.getKey(), e.getValue()});
     979            tags.put(e.getKey(), e.getValue().size() == 1
     980                    ? e.getValue().keySet().iterator().next() : tr("<different>"));
    988981        }
    989982
    990983        membershipData.setRowCount(0);
    public class PropertiesDialog extends ToggleDialog implements SelectionChangedLi 
    10251018            membershipData.addRow(new Object[]{r, roles.get(r)});
    10261019        }
    10271020
    1028         presets.updatePresets(nodes, ways, relations, closedways, valueCount, presetHandler);
     1021        presets.updatePresets(types, tags, presetHandler);
    10291022
    10301023        membershipTable.getTableHeader().setVisible(membershipData.getRowCount() > 0);
    10311024        membershipTable.setVisible(membershipData.getRowCount() > 0);
  • src/org/openstreetmap/josm/gui/tagging/TagEditorPanel.java

    diff --git a/src/org/openstreetmap/josm/gui/tagging/TagEditorPanel.java b/src/org/openstreetmap/josm/gui/tagging/TagEditorPanel.java
    index 55fc577..65fbc8e 100644
    a b import java.awt.BorderLayout; 
    55import java.awt.GridBagConstraints;
    66import java.awt.GridBagLayout;
    77import java.awt.Insets;
    8 import java.util.HashMap;
    9 import java.util.Map;
    10 import java.util.Map.Entry;
     8import java.util.EnumSet;
    119
    1210import javax.swing.BoxLayout;
    1311import javax.swing.JButton;
    public class TagEditorPanel extends JPanel { 
    180178    }
    181179
    182180    private void updatePresets() {
    183         Map<String, Map<String, Integer>> valuesCount = new HashMap<String, Map<String,Integer>>();
    184         for (Entry<String, String> entry: model.getTags().entrySet()) {
    185             Map<String, Integer> values = new HashMap<String, Integer>();
    186             values.put(entry.getValue(), 1);
    187             valuesCount.put(entry.getKey(), values);
    188         }
    189         presetListPanel.updatePresets(0, 0, 1, 0, valuesCount, presetHandler);
     181        presetListPanel.updatePresets(
     182                EnumSet.of(TaggingPreset.PresetType.RELATION),
     183                model.getTags(), presetHandler);
    190184        validate();
    191185    }
    192186}
  • src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java

    diff --git a/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java b/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java
    index 6fc18f2..d2ac05a 100644
    a b public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    107107        public String getName() {
    108108            return name().toLowerCase();
    109109        }
     110
     111        public static PresetType forPrimitive(OsmPrimitive p) {
     112            return forPrimitiveType(p.getType());
     113        }
     114
     115        public static PresetType forPrimitiveType(org.openstreetmap.josm.data.osm.OsmPrimitiveType type) {
     116            switch (type) {
     117                case NODE:
     118                    return NODE;
     119                case WAY:
     120                    return WAY;
     121                case CLOSEDWAY:
     122                    return CLOSEDWAY;
     123                case RELATION:
     124                    return RELATION;
     125                default:
     126                    throw new IllegalArgumentException();
     127            }
     128        }
     129    }
     130
     131    /**
     132     * Enum denoting the way how a match (see {@link Item#matches}) is performed.
     133     */
     134    private enum MatchType {
     135
     136        /**
     137         * Neutral, i.e., o not consider this item for matching.
     138         */
     139        NONE("none"), /**
     140         * Positive if key matches, neutral otherwise.
     141         */
     142        KEY("key"),
     143        /**
     144         * Positive if key matches, negative otherwise.
     145         */
     146        KEY_REQUIRED("key!"),
     147        /**
     148         * Positive if key and value matches, negative otherwise.
     149         */
     150        KEY_VALUE("keyvalue");
     151        private final String value;
     152
     153        private MatchType(String value) {
     154            this.value = value;
     155        }
     156
     157        public String getValue() {
     158            return value;
     159        }
     160
     161        public static MatchType ofString(String type) {
     162            for (MatchType i : EnumSet.allOf(MatchType.class)) {
     163                if (i.getValue().equals(type)) {
     164                    return i;
     165                }
     166            }
     167            throw new IllegalArgumentException(type + " is not allowed");
     168        }
    110169    }
    111170
    112171    public static final int DIALOG_ANSWER_APPLY = 1;
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    139198        boolean requestFocusInWindow() {
    140199            return false;
    141200        }
     201
     202        /**
     203         * Tests whether the tags match this item.
     204         * @param tags the tags of an {@link OsmPrimitive}
     205         * @return {@code true} if matches (positive), {@code null} if neutral, {@code false} if mismatches (negative).
     206         */
     207        abstract Boolean matches(Map<String, String> tags);
    142208    }
    143209
    144210    public static class Usage {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    244310        public String text;
    245311        public String locale_text;
    246312        public String text_context;
    247         public String default_;
     313        public String default_ = "";
    248314        public String originalValue;
    249315        public String use_last_as_default = "false";
    250         public boolean delete_if_empty = false;
     316        @Deprecated
     317        public boolean delete_if_empty = true;
     318        @Deprecated
    251319        public boolean required = false;
     320        public String match = MatchType.NONE.getValue();
    252321
    253322        private JComponent value;
    254323
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    325394        boolean requestFocusInWindow() {
    326395            return value.requestFocusInWindow();
    327396        }
     397
     398        @Override
     399        Boolean matches(Map<String, String> tags) {
     400            switch (MatchType.ofString(match)) {
     401                case NONE:
     402                    return null;
     403                case KEY:
     404                    return tags.containsKey(key) ? true : null;
     405                case KEY_REQUIRED:
     406                    return tags.containsKey(key);
     407                default:
     408                    throw new IllegalArgumentException("key_value matching not supported for <text>: " + text);
     409            }
     410        }
    328411    }
    329412
    330413    public static class Check extends Item {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    336419        public String value_on = OsmUtils.trueval;
    337420        public String value_off = OsmUtils.falseval;
    338421        public boolean default_ = false; // only used for tagless objects
     422        @Deprecated
    339423        public boolean required = false;
     424        public String match = MatchType.NONE.getValue();
    340425
    341426        private QuadStateCheckBox check;
    342427        private QuadStateCheckBox.State initialState;
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    410495                            null));
    411496        }
    412497        @Override boolean requestFocusInWindow() {return check.requestFocusInWindow();}
     498
     499        @Override
     500        Boolean matches(Map<String, String> tags) {
     501            switch (MatchType.ofString(match)) {
     502                case NONE:
     503                    return null;
     504                case KEY:
     505                    return tags.containsKey(key) ? true : null;
     506                case KEY_REQUIRED:
     507                    return tags.containsKey(key);
     508                case KEY_VALUE:
     509                    return value_off.equals(tags.get(key)) || value_on.equals(tags.get(key));
     510                default:
     511                    throw new IllegalStateException();
     512            }
     513        }
    413514    }
    414515
    415516    public static abstract class ComboMultiSelect extends Item {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    426527        public String locale_short_descriptions;
    427528        public String default_;
    428529        public String delimiter = ";";
    429         public boolean delete_if_empty = false;
     530        @Deprecated
     531        public boolean delete_if_empty = true;
    430532        public String use_last_as_default = "false";
     533        @Deprecated
    431534        public boolean required = false;
     535        public String match = MatchType.NONE.getValue();
    432536
    433537        protected List<String> short_description_list;
    434538        protected JComponent component;
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    439543        protected abstract Object getSelectedItem();
    440544        protected abstract void addToPanelAnchor(JPanel p, String def, String[] display_array);
    441545
     546        protected char getDelChar() {
     547            return delimiter.isEmpty() ? ';' : delimiter.charAt(0);
     548        }
     549
    442550        @Override
    443551        public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
    444552
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    446554            usage = determineTextUsage(sel, key);
    447555            String def = default_;
    448556
    449             char delChar = ';';
    450             if (!delimiter.isEmpty()) {
    451                 delChar = delimiter.charAt(0);
    452             }
     557            char delChar = getDelChar();
    453558
    454559            String[] value_array = splitEscaped(delChar, values);
    455560            String[] display_array;
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    607712                }
    608713            };
    609714        }
     715
     716        @Override
     717        Boolean matches(Map<String, String> tags) {
     718            switch (MatchType.ofString(match)) {
     719                case NONE:
     720                    return null;
     721                case KEY:
     722                    return tags.containsKey(key) ? true : null;
     723                case KEY_REQUIRED:
     724                    return tags.containsKey(key);
     725                case KEY_VALUE:
     726                    return tags.containsKey(key)
     727                            && Arrays.asList(splitEscaped(getDelChar(), values)).contains(tags.get(key));
     728                default:
     729                    throw new IllegalStateException();
     730            }
     731        }
    610732    }
    611733
    612734    public static class Combo extends ComboMultiSelect {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    827949        @Override
    828950        public void addCommands(List<Tag> changedTags) {
    829951        }
     952
     953        @Override
     954        Boolean matches(Map<String, String> tags) {
     955            return null;
     956        }
    830957    }
    831958
    832959    public static class Link extends Item {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    861988        @Override
    862989        public void addCommands(List<Tag> changedTags) {
    863990        }
     991
     992        @Override
     993        Boolean matches(Map<String, String> tags) {
     994            return null;
     995        }
    864996    }
    865997
    866998    public static class Role {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    8701002        public String text_context;
    8711003        public String locale_text;
    8721004
    873         public boolean required=false;
     1005        public boolean required = false;
    8741006        public long count = 0;
    8751007
    8761008        public void setType(String types) throws SAXException {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    9551087        @Override
    9561088        public void addCommands(List<Tag> changedTags) {
    9571089        }
     1090
     1091        @Override
     1092        Boolean matches(Map<String, String> tags) {
     1093            return null;
     1094        }
    9581095    }
    9591096
    9601097    public static class Optional extends Item {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    9711108        @Override
    9721109        public void addCommands(List<Tag> changedTags) {
    9731110        }
     1111
     1112        @Override
     1113        Boolean matches(Map<String, String> tags) {
     1114            return null;
     1115        }
    9741116    }
    9751117
    9761118    public static class Space extends Item {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    9841126        @Override
    9851127        public void addCommands(List<Tag> changedTags) {
    9861128        }
     1129
     1130        @Override
     1131        Boolean matches(Map<String, String> tags) {
     1132            return null;
     1133        }
    9871134    }
    9881135
    9891136    public static class Key extends Item {
    9901137
    9911138        public String key;
    9921139        public String value;
     1140        public String match = MatchType.KEY_VALUE.getValue();
    9931141
    9941142        @Override
    9951143        public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    10001148        public void addCommands(List<Tag> changedTags) {
    10011149            changedTags.add(new Tag(key, value));
    10021150        }
     1151
     1152        @Override
     1153        Boolean matches(Map<String, String> tags) {
     1154            switch (MatchType.ofString(match)) {
     1155                case NONE:
     1156                    return null;
     1157                case KEY:
     1158                    return tags.containsKey(key) ? true : null;
     1159                case KEY_REQUIRED:
     1160                    return tags.containsKey(key);
     1161                case KEY_VALUE:
     1162                    return value.equals(tags.get(key));
     1163                default:
     1164                    throw new IllegalStateException();
     1165            }
     1166        }
    10031167    }
    10041168
    10051169    /**
    public class TaggingPreset extends AbstractAction implements MapView.LayerChange 
    14851649    public String toString() {
    14861650        return (types == null?"":types) + " " + name;
    14871651    }
     1652
     1653    public boolean matches(Collection<PresetType> t, Map<String, String> tags) {
     1654        if (!isShowable()) {
     1655            return false;
     1656        }
     1657        if (t != null && !types.containsAll(t)) {
     1658            return false;
     1659        }
     1660        boolean atLeastOnePositiveMatch = false;
     1661        for (Item item : data) {
     1662            Boolean m = item.matches(tags);
     1663            if (m != null && !m) {
     1664                return false;
     1665            } else if (m != null) {
     1666                atLeastOnePositiveMatch = true;
     1667            }
     1668        }
     1669        return atLeastOnePositiveMatch;
     1670    }
    14881671}
  • src/org/openstreetmap/josm/tools/TaggingPresetNameTemplateList.java

    diff --git a/src/org/openstreetmap/josm/tools/TaggingPresetNameTemplateList.java b/src/org/openstreetmap/josm/tools/TaggingPresetNameTemplateList.java
    index 6792206..c9e252a 100644
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.tools;
    33
    4 import java.util.ArrayList;
     4import java.util.EnumSet;
     5import java.util.LinkedList;
    56import java.util.List;
    67
    78import org.openstreetmap.josm.data.osm.OsmPrimitive;
    8 import org.openstreetmap.josm.data.osm.Way;
    99import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference;
    1010import org.openstreetmap.josm.gui.tagging.TaggingPreset;
    11 import org.openstreetmap.josm.gui.tagging.TaggingPreset.Check;
    12 import org.openstreetmap.josm.gui.tagging.TaggingPreset.Combo;
    1311import org.openstreetmap.josm.gui.tagging.TaggingPreset.PresetType;
    14 import org.openstreetmap.josm.gui.tagging.TaggingPreset.Text;
    1512
    1613/**
    1714 * List of tagging presets with name templates, allows to find appropriate template based on existing primitive
    public class TaggingPresetNameTemplateList { 
    2623        }
    2724        return instance;
    2825    }
    29 
    30     private final List<TaggingPreset> presetsWithPattern = new ArrayList<TaggingPreset>();
     26    private final List<TaggingPreset> presetsWithPattern = new LinkedList<TaggingPreset>();
    3127
    3228    private TaggingPresetNameTemplateList() {
    3329        if (TaggingPresetPreference.taggingPresets != null) {
    34             for (TaggingPreset tp: TaggingPresetPreference.taggingPresets) {
     30            for (TaggingPreset tp : TaggingPresetPreference.taggingPresets) {
    3531                if (tp.nameTemplate != null) {
    3632                    presetsWithPattern.add(tp);
    3733                }
    public class TaggingPresetNameTemplateList { 
    4137
    4238    public TaggingPreset findPresetTemplate(OsmPrimitive primitive) {
    4339
    44         PresetType presetType;
    45         switch (primitive.getType()) {
    46         case NODE:
    47             presetType = PresetType.NODE;
    48             break;
    49         case WAY:
    50             if (((Way) primitive).isClosed()) {
    51                 presetType = PresetType.CLOSEDWAY;
    52             } else {
    53                 presetType = PresetType.WAY;
     40        for (TaggingPreset t : presetsWithPattern) {
     41            if (t.matches(EnumSet.of(PresetType.forPrimitive(primitive)), primitive.getKeys())) {
     42                return t;
    5443            }
    55             break;
    56         case RELATION:
    57             presetType = PresetType.RELATION;
    58             break;
    59         default:
    60             throw new AssertionError();
    6144        }
    62 
    63         for(TaggingPreset t : presetsWithPattern) {
    64 
    65 
    66             if (       t.types == null
    67                     || t.types.contains(presetType)
    68                     || (presetType == PresetType.CLOSEDWAY && t.types.contains(PresetType.WAY))) {
    69                 int found = 0;
    70 
    71                 if (t.nameTemplateFilter != null) {
    72                     if (t.nameTemplateFilter.match(primitive))
    73                         return t;
    74                     else {
    75                         continue;
    76                     }
    77                 }
    78 
    79                 for(TaggingPreset.Item i : t.data) {
    80                     if(i instanceof TaggingPreset.Key) {
    81                         String val = ((TaggingPreset.Key)i).value;
    82                         String key = ((TaggingPreset.Key)i).key;
    83                         // we subtract 100 if not found and add 1 if found
    84                         if (val != null && val.equals(primitive.get(key))) {
    85                             found+=1;
    86                         } else {
    87                             found-=100;
    88                         }
    89                     } else {
    90                         String key = null;
    91                         if ((i instanceof Text) && ((Text)i).required) {
    92                             key = ((Text)i).key;
    93                         } else if ((i instanceof Combo) && ((Combo)i).required) {
    94                             key = ((Combo)i).key;
    95                         } else if ((i instanceof Check) && ((Check)i).required) {
    96                             key = ((Check)i).key;
    97                         }
    98                         if (key != null) {
    99                             if (primitive.get(key) != null) {
    100                                 found += 1;
    101                             } else {
    102                                 found -= 100;
    103                             }
    104                         }
    105                     }
    106                 }
    107 
    108                 if(found > 0)
    109                     return t; // First matching preset wins
    110             }
    111         }
    112 
    11345        return null;
    114 
    11546    }
    116 
    117 
    11847}