Index: /trunk/data/defaultpresets.xml
===================================================================
--- /trunk/data/defaultpresets.xml	(revision 7209)
+++ /trunk/data/defaultpresets.xml	(revision 7210)
@@ -2530,5 +2530,5 @@
             </optional>
             <roles>
-                <role key="" text="route segment" requisite="required" type="way" />
+                <role key="" text="route segment" requisite="required" type="way" member_expression="highway OR railway OR waterway OR aerialway" />
                 <role key="stop" text="stop position" requisite="optional" type="node" member_expression="public_transport=stop_position" />
                 <role key="stop_exit_only" text="stop position (exit only)" requisite="optional" type="node" member_expression="public_transport=stop_position" />
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetSelector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetSelector.java	(revision 7209)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetSelector.java	(revision 7210)
@@ -20,4 +20,5 @@
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 
@@ -42,8 +43,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.SelectionChangedListener;
-import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.gui.tagging.TaggingPresetItems.Key;
@@ -76,5 +74,5 @@
     private final EnumSet<TaggingPresetType> typesInSelection = EnumSet.noneOf(TaggingPresetType.class);
     private boolean typesInSelectionDirty = true;
-    private final List<PresetClassification> classifications = new ArrayList<>();
+    private final PresetClassifications classifications = new PresetClassifications();
     private ResultListModel lsResultModel = new ResultListModel();
 
@@ -117,5 +115,8 @@
     }
 
-    private static class PresetClassification implements Comparable<PresetClassification> {
+    /**
+     * Computes the match ration of a {@link TaggingPreset} wrt. a searchString.
+     */
+    static class PresetClassification implements Comparable<PresetClassification> {
         public final TaggingPreset preset;
         public int classification;
@@ -209,5 +210,5 @@
     public TaggingPresetSelector(boolean displayOnlyApplicable, boolean displaySearchInTags) {
         super(new BorderLayout());
-        loadPresets(TaggingPresets.getTaggingPresets());
+        classifications.loadPresets(TaggingPresets.getTaggingPresets());
 
         edSearchText = new JosmTextField();
@@ -321,75 +322,114 @@
         //TODO Save favorites to file
         String text = edSearchText.getText().toLowerCase();
-
-        String[] groupWords;
-        String[] nameWords;
-
-        if (text.contains("/")) {
-            groupWords = text.substring(0, text.lastIndexOf('/')).split("[\\s/]");
-            nameWords = text.substring(text.indexOf('/') + 1).split("\\s");
-        } else {
-            groupWords = null;
-            nameWords = text.split("\\s");
-        }
-
         boolean onlyApplicable = ckOnlyApplicable != null && ckOnlyApplicable.isSelected();
         boolean inTags = ckSearchInTags != null && ckSearchInTags.isSelected();
 
-        final List<PresetClassification> result = new ArrayList<>();
-        for (PresetClassification presetClassification : classifications) {
-            TaggingPreset preset = presetClassification.preset;
-            presetClassification.classification = 0;
-
-            if (onlyApplicable) {
-                boolean suitable = preset.typeMatches(getTypesInSelection());
-
-                if (!suitable && preset.types.contains(TaggingPresetType.RELATION) && preset.roles != null) {
-                    final Predicate<Role> memberExpressionMatchesOnePrimitive = new Predicate<Role>() {
-                        final Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
-                        @Override public boolean evaluate(Role object) {
-                            return object.memberExpression != null
-                                    && Utils.exists(selected, object.memberExpression);
+        final List<PresetClassification> result = classifications.getMatchingPresets(
+                text, onlyApplicable, inTags, getTypesInSelection(), Main.main.getCurrentDataSet().getSelected());
+
+        lsResultModel.setPresets(result);
+
+    }
+
+    /**
+     * A collection of {@link PresetClassification}s with the functionality of filtering wrt. searchString.
+     */
+    static class PresetClassifications implements Iterable<PresetClassification> {
+
+        private final List<PresetClassification> classifications = new ArrayList<>();
+
+        public List<PresetClassification> getMatchingPresets(String searchText, boolean onlyApplicable, boolean inTags, EnumSet<TaggingPresetType> presetTypes, final Collection<? extends OsmPrimitive> selectedPrimitives) {
+            final String[] groupWords;
+            final String[] nameWords;
+
+            if (searchText.contains("/")) {
+                groupWords = searchText.substring(0, searchText.lastIndexOf('/')).split("[\\s/]");
+                nameWords = searchText.substring(searchText.indexOf('/') + 1).split("\\s");
+            } else {
+                groupWords = null;
+                nameWords = searchText.split("\\s");
+            }
+
+            return getMatchingPresets(groupWords, nameWords, onlyApplicable, inTags, presetTypes, selectedPrimitives);
+        }
+
+        public List<PresetClassification> getMatchingPresets(String[] groupWords, String[] nameWords, boolean onlyApplicable, boolean inTags, EnumSet<TaggingPresetType> presetTypes, final Collection<? extends OsmPrimitive> selectedPrimitives) {
+
+            final List<PresetClassification> result = new ArrayList<>();
+            for (PresetClassification presetClassification : classifications) {
+                TaggingPreset preset = presetClassification.preset;
+                presetClassification.classification = 0;
+
+                if (onlyApplicable) {
+                    boolean suitable = preset.typeMatches(presetTypes);
+
+                    if (!suitable && preset.types.contains(TaggingPresetType.RELATION) && preset.roles != null && !preset.roles.roles.isEmpty()) {
+                        final Predicate<Role> memberExpressionMatchesOnePrimitive = new Predicate<Role>() {
+
+                            @Override
+                            public boolean evaluate(Role object) {
+                                return object.memberExpression != null
+                                        && Utils.exists(selectedPrimitives, object.memberExpression);
+                            }
+                        };
+                        suitable = Utils.exists(preset.roles.roles, memberExpressionMatchesOnePrimitive);
+                        // keep the preset to allow the creation of new relations
+                    }
+                    if (!suitable) {
+                        continue;
+                    }
+                }
+
+                if (groupWords != null && presetClassification.isMatchingGroup(groupWords) == 0) {
+                    continue;
+                }
+
+                int matchName = presetClassification.isMatchingName(nameWords);
+
+                if (matchName == 0) {
+                    if (groupWords == null) {
+                        int groupMatch = presetClassification.isMatchingGroup(nameWords);
+                        if (groupMatch > 0) {
+                            presetClassification.classification = CLASSIFICATION_GROUP_MATCH + groupMatch;
                         }
-                    };
-                    suitable = Utils.exists(preset.roles.roles, memberExpressionMatchesOnePrimitive);
-                    // keep the preset to allow the creation of new relations
-                }
-                if (!suitable) {
+                    }
+                    if (presetClassification.classification == 0 && inTags) {
+                        int tagsMatch = presetClassification.isMatchingTags(nameWords);
+                        if (tagsMatch > 0) {
+                            presetClassification.classification = CLASSIFICATION_TAGS_MATCH + tagsMatch;
+                        }
+                    }
+                } else {
+                    presetClassification.classification = CLASSIFICATION_NAME_MATCH + matchName;
+                }
+
+                if (presetClassification.classification > 0) {
+                    presetClassification.classification += presetClassification.favoriteIndex;
+                    result.add(presetClassification);
+                }
+            }
+
+            Collections.sort(result);
+            return result;
+
+        }
+
+        public void clear() {
+            classifications.clear();
+        }
+
+        public void loadPresets(Collection<TaggingPreset> presets) {
+            for (TaggingPreset preset : presets) {
+                if (preset instanceof TaggingPresetSeparator || preset instanceof TaggingPresetMenu) {
                     continue;
                 }
-            }
-
-            if (groupWords != null && presetClassification.isMatchingGroup(groupWords) == 0) {
-                continue;
-            }
-
-            int matchName = presetClassification.isMatchingName(nameWords);
-
-            if (matchName == 0) {
-                if (groupWords == null) {
-                    int groupMatch = presetClassification.isMatchingGroup(nameWords);
-                    if (groupMatch > 0) {
-                        presetClassification.classification = CLASSIFICATION_GROUP_MATCH + groupMatch;
-                    }
-                }
-                if (presetClassification.classification == 0 && inTags) {
-                    int tagsMatch = presetClassification.isMatchingTags(nameWords);
-                    if (tagsMatch > 0) {
-                        presetClassification.classification = CLASSIFICATION_TAGS_MATCH + tagsMatch;
-                    }
-                }
-            } else {
-                presetClassification.classification = CLASSIFICATION_NAME_MATCH + matchName;
-            }
-
-            if (presetClassification.classification > 0) {
-                presetClassification.classification += presetClassification.favoriteIndex;
-                result.add(presetClassification);
-            }
-        }
-
-        Collections.sort(result);
-        lsResultModel.setPresets(result);
-
+                classifications.add(new PresetClassification(preset));
+            }
+        }
+
+        @Override
+        public Iterator<PresetClassification> iterator() {
+            return classifications.iterator();
+        }
     }
 
@@ -401,16 +441,5 @@
                 if (Main.main==null || Main.main.getCurrentDataSet() == null) return typesInSelection;
                 for (OsmPrimitive primitive : Main.main.getCurrentDataSet().getSelected()) {
-                    if (primitive instanceof Node) {
-                        typesInSelection.add(TaggingPresetType.NODE);
-                    } else if (primitive instanceof Way) {
-                        if (((Way) primitive).isClosed()) {
-                            typesInSelection.add(TaggingPresetType.CLOSEDWAY);
-                        } else {
-                            // closedway is not a way for preset checking, the types are mutually exclusive
-                            typesInSelection.add(TaggingPresetType.WAY);
-                        }
-                    } else if (primitive instanceof Relation) {
-                        typesInSelection.add(TaggingPresetType.RELATION);
-                    }
+                    typesInSelection.add(TaggingPresetType.forPrimitive(primitive));
                 }
             }
@@ -435,5 +464,5 @@
     public void init(Collection<TaggingPreset> presets) {
         classifications.clear();
-        loadPresets(presets);
+        classifications.loadPresets(presets);
         init();
     }
@@ -477,13 +506,4 @@
     }
 
-    private void loadPresets(Collection<TaggingPreset> presets) {
-        for (TaggingPreset preset: presets) {
-            if (preset instanceof TaggingPresetSeparator || preset instanceof TaggingPresetMenu) {
-                continue;
-            }
-            classifications.add(new PresetClassification(preset));
-        }
-    }
-
     public void setSelectedPreset(TaggingPreset p) {
         lsResult.setSelectedValue(p, true);
Index: /trunk/test/unit/org/openstreetmap/josm/gui/tagging/PresetClassificationsTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/tagging/PresetClassificationsTest.java	(revision 7210)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/tagging/PresetClassificationsTest.java	(revision 7210)
@@ -0,0 +1,69 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.tagging;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.TestUtils;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.tools.Utils;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+
+public class PresetClassificationsTest {
+
+    final static TaggingPresetSelector.PresetClassifications classifications = new TaggingPresetSelector.PresetClassifications();
+
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() throws IOException, SAXException {
+        JOSMFixture.createUnitTestFixture().init();
+        final Collection<TaggingPreset> presets = TaggingPresetReader.readAll("resource://data/defaultpresets.xml", true);
+        classifications.loadPresets(presets);
+    }
+
+    private List<TaggingPresetSelector.PresetClassification> getMatchingPresets(String searchText, OsmPrimitive w) {
+        return classifications.getMatchingPresets(searchText, true, true, EnumSet.of(TaggingPresetType.forPrimitive(w)), Collections.singleton(w));
+    }
+
+    private List<String> getMatchingPresetNames(String searchText, OsmPrimitive w) {
+        return Utils.transform(getMatchingPresets(searchText, w), new Utils.Function<TaggingPresetSelector.PresetClassification, String>() {
+            @Override
+            public String apply(TaggingPresetSelector.PresetClassification x) {
+                return x.preset.name;
+            }
+        });
+    }
+
+    @Test
+    public void testBuilding() throws Exception {
+        final Way w = new Way();
+        final Node n1 = new Node();
+        w.addNode(n1);
+        w.addNode(new Node());
+        w.addNode(new Node());
+        assertTrue("unclosed way should not match building preset", !getMatchingPresetNames("building", w).contains("Building"));
+        w.addNode(n1);
+        assertTrue("closed way should match building preset", getMatchingPresetNames("building", w).contains("Building"));
+    }
+
+    @Test
+    public void testRelationsForTram() {
+        final OsmPrimitive tram = TestUtils.createPrimitive("way railway=tram");
+        assertTrue("railway=tram should match 'Railway route' for relation creation", getMatchingPresetNames("route", tram).contains("Railway route"));
+        assertTrue("railway=tram should match 'Public transport route' for relation creation", getMatchingPresetNames("route", tram).contains("Public transport route"));
+        assertTrue("railway=tram should not match 'Bus route'", !getMatchingPresetNames("route", tram).contains("Bus route"));
+    }
+
+}
