Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java	(revision 33107)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java	(revision 33108)
@@ -44,546 +44,542 @@
 public class PTAssistantValidatorTest extends Test {
 
-    public static final int ERROR_CODE_SORTING = 3711;
-    public static final int ERROR_CODE_ROAD_TYPE = 3721;
-    public static final int ERROR_CODE_CONSTRUCTION = 3722;
-    public static final int ERROR_CODE_DIRECTION = 3731;
-    public static final int ERROR_CODE_END_STOP = 3741;
-    public static final int ERROR_CODE_SPLIT_WAY = 3742;
-    public static final int ERROR_CODE_RELAITON_MEMBER_ROLES = 3743;
-    public static final int ERROR_CODE_SOLITARY_STOP_POSITION = 3751;
-    public static final int ERROR_CODE_PLATFORM_PART_OF_HIGHWAY = 3752;
-    public static final int ERROR_CODE_STOP_NOT_SERVED = 3753;
-    public static final int ERROR_CODE_STOP_BY_STOP = 3754;
-    public static final int ERROR_CODE_NOT_PART_OF_STOP_AREA = 3761;
-    public static final int ERROR_CODE_STOP_AREA_NO_STOPS = 3762;
-    public static final int ERROR_CODE_STOP_AREA_NO_PLATFORM = 3763;
-    public static final int ERROR_CODE_STOP_AREA_COMPARE_RELATIONS = 3764;
-
-    private PTAssistantLayer layer;
-
-    public PTAssistantValidatorTest() {
-        super(tr("Public Transport Assistant tests"),
-                tr("Check if route relations are compatible with public transport version 2"));
-
-        layer = PTAssistantLayer.getLayer();
-        DataSet.addSelectionListener(layer);
-
-    }
-
-    @Override
-    public void visit(Node n) {
-
-        if (n.isIncomplete()) {
-            return;
-        }
-
-        NodeChecker nodeChecker = new NodeChecker(n, this);
-
-        // select only stop_positions
-        if (n.hasTag("public_transport", "stop_position")) {
-
-            // check if stop positions are on a way:
-            nodeChecker.performSolitaryStopPositionTest();
-
-            if (Main.pref.getBoolean("pt_assistant.stop-area-tests", true) == true) {
-                // check if stop positions are in any stop_area relation:
-                nodeChecker.performNodePartOfStopAreaTest();
-            }
-
-        }
-
-        // select only platforms
-        if (n.hasTag("public_transport", "platform")) {
-
-            // check that platforms are not part of any way:
-            nodeChecker.performPlatformPartOfWayTest();
-
-            if (Main.pref.getBoolean("pt_assistant.stop-area-tests", true) == true) {
-                // check if platforms are in any stop_area relation:
-                nodeChecker.performNodePartOfStopAreaTest();
-            }
-
-        }
-
-        this.errors.addAll(nodeChecker.getErrors());
-
-    }
-
-    @Override
-    public void visit(Relation r) {
-
-        // Download incomplete members. If the download does not work, return
-        // and do not do any testing.
-        if (r.hasIncompleteMembers()) {
-
-            boolean downloadSuccessful = this.downloadIncompleteMembers();
-            if (!downloadSuccessful) {
-                return;
-            }
-        }
-
-        if (r.hasIncompleteMembers()) {
-            return;
-        }
-
-
-        // Do some testing on stop area relations
-        if (Main.pref.getBoolean("pt_assistant.stop-area-tests", true) == true && StopUtils.isStopArea(r)) {
-
-            StopChecker stopChecker = new StopChecker(r, this);
-
-            // Check if stop area relation has one stop position.
-            stopChecker.performStopAreaStopPositionTest();
-
-            // Check if stop area relation has one platform.
-            stopChecker.performStopAreaPlatformTest();
-
-            // Check if stop position(s) belong the same route relation as
-            // related platform(s)
-            stopChecker.performStopAreaRelationsTest();
-
-            // Attach thrown errors
-            this.errors.addAll(stopChecker.getErrors());
-        }
-
-
-        if (!RouteUtils.isTwoDirectionRoute(r)) {
-            return;
-        }
-
-        // Check individual ways using the oneway direction test and the road
-        // type test:
-        WayChecker wayChecker = new WayChecker(r, this);
-        wayChecker.performDirectionTest();
-        wayChecker.performRoadTypeTest();
-        this.errors.addAll(wayChecker.getErrors());
-
-        proceedWithSorting(r);
-
-        // This allows to modify the route before the sorting and
-        // SegmentChecker are carried out:
-        // if (this.errors.isEmpty()) {
-        // proceedWithSorting(r);
-        // } else {
-        // this.proceedAfterWayCheckerErrors(r);
-        // }
-
-    }
-
-    /**
-     * Downloads incomplete relation members in an extra thread (user input
-     * required)
-     *
-     * @return true if successful, false if not successful
-     */
-    private boolean downloadIncompleteMembers() {
-
-        final int[] userSelection = {0};
-
-        try {
-
-            if (SwingUtilities.isEventDispatchThread()) {
-
-                userSelection[0] = showIncompleteMembersDownloadDialog();
-
-            } else {
-
-                SwingUtilities.invokeAndWait(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            userSelection[0] = showIncompleteMembersDownloadDialog();
-                        } catch (InterruptedException e) {
-                            e.printStackTrace();
-                        }
-
-                    }
-                });
-
-            }
-
-        } catch (InterruptedException | InvocationTargetException e) {
-            return false;
-        }
-
-        if (userSelection[0] == JOptionPane.YES_OPTION) {
-
-            Thread t = new IncompleteMembersDownloadThread();
-            t.start();
-            synchronized (t) {
-                try {
-                    t.wait();
-                } catch (InterruptedException e) {
-                    return false;
-                }
-            }
-
-        }
-
-        return true;
-
-    }
-
-    /**
-     * Shows the dialog asking the user about an incomplete member download
-     *
-     * @return user's selection
-     * @throws InterruptedException if interrupted
-     */
-    private int showIncompleteMembersDownloadDialog() throws InterruptedException {
-
-        if (Main.pref.getBoolean("pt_assistant.download-incomplete", false) == true) {
-            return JOptionPane.YES_OPTION;
-        }
-
-        if (Main.pref.getBoolean("pt_assistant.download-incomplete", false) == false) {
-            return JOptionPane.NO_OPTION;
-        }
-
-        IncompleteMembersDownloadDialog incompleteMembersDownloadDialog = new IncompleteMembersDownloadDialog();
-        return incompleteMembersDownloadDialog.getUserSelection();
-
-    }
-
-    /**
-     * Gets user input after errors were detected by WayChecker. Although this
-     * method is not used in the current implementation, it can be used to fix
-     * errors from the previous testing stage and modify the route before the
-     * second stage of testing is carried out.
-     */
-    @SuppressWarnings("unused")
-    private void proceedAfterWayCheckerErrors(Relation r) {
-
-        // count errors of each type:
-        int numberOfDirectionErrors = 0;
-        int numberOfRoadTypeErrors = 0;
-        for (TestError e : this.errors) {
-            if (e.getCode() == ERROR_CODE_DIRECTION) {
-                numberOfDirectionErrors++;
-            }
-            if (e.getCode() == ERROR_CODE_ROAD_TYPE) {
-                numberOfRoadTypeErrors++;
-            }
-        }
-
-        final int[] userInput = {0};
-        final long idParameter = r.getId();
-        final int directionErrorParameter = numberOfDirectionErrors;
-        final int roadTypeErrorParameter = numberOfRoadTypeErrors;
-
-        if (SwingUtilities.isEventDispatchThread()) {
-
-            userInput[0] = showProceedDialog(idParameter, directionErrorParameter, roadTypeErrorParameter);
-
-        } else {
-
-            try {
-                SwingUtilities.invokeAndWait(new Runnable() {
-                    @Override
-                    public void run() {
-                        userInput[0] = showProceedDialog(idParameter, directionErrorParameter, roadTypeErrorParameter);
-
-                    }
-                });
-            } catch (InvocationTargetException | InterruptedException e1) {
-                e1.printStackTrace();
-            }
-
-        }
-
-        if (userInput[0] == 0) {
-            this.fixErrorFromPlugin(this.errors);
-            proceedWithSorting(r);
-            return;
-        }
-
-        if (userInput[0] == 1) {
-            JOptionPane.showMessageDialog(null, "This is not implemented yet!");
-            return;
-        }
-
-        if (userInput[0] == 2) {
-            proceedWithSorting(r);
-        }
-
-        // if userInput==-1 (i.e. no input), do nothing and stop testing of the
-        // route.
-
-    }
-
-    private int showProceedDialog(long id, int numberOfDirectionErrors, int numberOfRoadTypeErrors) {
-
-        if (numberOfDirectionErrors == 0 && numberOfRoadTypeErrors == 0) {
-            return 2;
-        }
-
-        if (Main.pref.getBoolean("pt_assistant.proceed-without-fix", true) == false) {
-            return 0;
-        }
-
-        if (Main.pref.getBoolean("pt_assistant.proceed-without-fix", true) == true) {
-            return 2;
-        }
-
-        ProceedDialog proceedDialog = new ProceedDialog(id, numberOfDirectionErrors, numberOfRoadTypeErrors);
-        return proceedDialog.getUserSelection();
-
-    }
-
-    /**
-     * Carries out the second stage of the testing: sorting
-     *
-     * @param r relation
-     */
-    private void proceedWithSorting(Relation r) {
-
-        // Check if the relation is correct, or only has a wrong sorting order:
-        RouteChecker routeChecker = new RouteChecker(r, this);
-        routeChecker.performSortingTest();
-        List<TestError> routeCheckerErrors = routeChecker.getErrors();
-
-        /*- At this point, there are 3 variants:
-         *
-         * 1) There are no errors => route is correct
-         * 2) There is only a sorting error (can only be 1), but otherwise
-         * correct.
-         * 3) There are some other errors/gaps that cannot be fixed by
-         * sorting => start further test (stop-by-stop)
-         *
-         * */
-
-        if (!routeCheckerErrors.isEmpty()) {
-            // Variant 2
-            // If there is only the sorting error, add it
-            this.errors.addAll(routeChecker.getErrors());
-        }
-
-        // if (!routeChecker.getHasGap()) {
-        // // Variant 1
-        // storeCorrectRouteSegments(r);
-        // }
-
-        // Variant 3:
-        proceedAfterSorting(r);
-
-    }
-
-    /**
-     * Carries out the stop-by-stop testing which includes building the route
-     * data model.
-     *
-     * @param r route relation
-     */
-    private void proceedAfterSorting(Relation r) {
-
-        SegmentChecker segmentChecker = new SegmentChecker(r, this);
-
-        // Check if the creation of the route data model in the segment checker
-        // worked. If it did not, it means the roles in the route relation do
-        // not match the tags of the route members.
-        if (!segmentChecker.getErrors().isEmpty()) {
-            this.errors.addAll(segmentChecker.getErrors());
-        }
-
-        segmentChecker.performFirstStopTest();
-        segmentChecker.performLastStopTest();
-        segmentChecker.performStopNotServedTest();
-
-        boolean sortingErrorFound = false;
-        for (TestError error : this.errors) {
-            if (error.getCode() == ERROR_CODE_SORTING) {
-                sortingErrorFound = true;
-                break;
-            }
-        }
-        if (!sortingErrorFound) {
-            segmentChecker.performStopByStopTest();
-            segmentChecker.findFixes();
-        }
-
-        for (TestError error: segmentChecker.getErrors()) {
-            if (error.getCode() != PTAssistantValidatorTest.ERROR_CODE_RELAITON_MEMBER_ROLES) {
-                this.errors.add(error);
-            }
-        }
-    }
-    
-    /**
-     * Overrides the superclass method
-     */
-    public void startTest() {
-    	super.startTest(progressMonitor);
-    	SegmentChecker.reset();
-    }
-    
-    /**
-     * Method is called after all primitives has been visited, overrides the method of the superclass.
-     */
-    public void endTest() {
-    	
-    	// modify the error messages for the stop-by-stop test:
-    	SegmentChecker.modifyStopByStopErrorMessages();
-    	
-    	// add the stop-by-stop errors with modified messages:
-    	for (Entry<Builder, PTRouteSegment> entry: SegmentChecker.wrongSegmentBuilders.entrySet()) {    		
-    		TestError error = entry.getKey().build();
-    		SegmentChecker.wrongSegments.put(error, entry.getValue());
-    		this.errors.add(error);
-    	}
-    	
-    	super.endTest();
-
-    }
-
-    /**
-     * Creates the PTRouteSegments of a route that has been found correct and
-     * stores them in the list of correct route segments
-     *
-     * @param r
-     *            route relation
-     */
-    @SuppressWarnings("unused")
-    private void storeCorrectRouteSegments(Relation r) {
-        PTRouteDataManager manager = new PTRouteDataManager(r);
-        StopToWayAssigner assigner = new StopToWayAssigner(manager.getPTWays());
-        if (manager.getPTStops().size() > 1) {
-            for (int i = 1; i < manager.getPTStops().size(); i++) {
-                PTStop segmentStartStop = manager.getPTStops().get(i - 1);
-                PTStop segmentEndStop = manager.getPTStops().get(i);
-                Way segmentStartWay = assigner.get(segmentStartStop);
-                Way segmentEndWay = assigner.get(segmentEndStop);
-                List<PTWay> waysBetweenStops = manager.getPTWaysBetween(segmentStartWay, segmentEndWay);
-                PTRouteSegment routeSegment = new PTRouteSegment(segmentStartStop, segmentEndStop, waysBetweenStops, r);
-                SegmentChecker.addCorrectSegment(routeSegment);
-            }
-        }
-    }
-
-    /**
-     * Checks if the test error is fixable
-     */
-    @Override
-    public boolean isFixable(TestError testError) {
-        if (testError.getCode() == ERROR_CODE_DIRECTION || testError.getCode() == ERROR_CODE_ROAD_TYPE
-                || testError.getCode() == ERROR_CODE_CONSTRUCTION || testError.getCode() == ERROR_CODE_SORTING
-                || testError.getCode() == PTAssistantValidatorTest.ERROR_CODE_SOLITARY_STOP_POSITION
-                || testError.getCode() == PTAssistantValidatorTest.ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) {
-            return true;
-        }
-
-        if (testError.getCode() == ERROR_CODE_STOP_BY_STOP && SegmentChecker.isFixable(testError)) {
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Fixes the given error
-     */
-    @Override
-    public Command fixError(TestError testError) {
-
-        // repaint the relation in the pt_assistant layer:
-        if (testError.getPrimitives().iterator().next().getType().equals(OsmPrimitiveType.RELATION)) {
-            Relation relationToBeFixed = (Relation) testError.getPrimitives().iterator().next();
-            this.layer.repaint(relationToBeFixed);
-        }
-
-        // reset the last fix:
-        PTAssistantPlugin.setLastFix(null);
-
-        List<Command> commands = new ArrayList<>();
-
-        if (testError.getCode() == ERROR_CODE_ROAD_TYPE || testError.getCode() == ERROR_CODE_CONSTRUCTION) {
-            commands.add(WayChecker.fixErrorByZooming(testError));
-        }
-
-        if (testError.getCode() == ERROR_CODE_DIRECTION) {
-            commands.add(WayChecker.fixErrorByZooming(testError));
-
-        }
-
-        if (testError.getCode() == ERROR_CODE_SORTING) {
-            commands.add(RouteChecker.fixSortingError(testError));
-        }
-
-        if (testError.getCode() == ERROR_CODE_SOLITARY_STOP_POSITION
-                || testError.getCode() == ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) {
-            commands.add(NodeChecker.fixError(testError));
-        }
-
-        if (testError.getCode() == ERROR_CODE_STOP_BY_STOP) {
-            commands.add(SegmentChecker.fixError(testError));
-            // make sure the primitives of this testError are selected:
-            Collection<OsmPrimitive> primitivesToSelect = new ArrayList<>();
-            for (Object obj : testError.getPrimitives()) {
-                primitivesToSelect.add((OsmPrimitive) obj);
-            }
-            SelectCommand selectCommand = new SelectCommand(primitivesToSelect);
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    selectCommand.executeCommand();
-                }
-            });
-        }
-
-        if (commands.isEmpty()) {
-            return null;
-        }
-
-        if (commands.size() == 1) {
-            return commands.get(0);
-        }
-
-        return new SequenceCommand(tr("Fix error"), commands);
-    }
-
-    /**
-     * This method is the counterpart of the fixError(TestError testError)
-     * method. The fixError method is invoked from the core validator (e.g. when
-     * user presses the "Fix" button in the validator). This method is invoken
-     * when the fix is initiated from within the plugin (e.g. automated fixes).
-     */
-    private void fixErrorFromPlugin(List<TestError> testErrors) {
-
-        // run fix task asynchronously
-        FixTask fixTask = new FixTask(testErrors);
-
-        Thread t = new Thread(fixTask);
-        t.start();
-        try {
-            t.join();
-            errors.removeAll(testErrors);
-
-        } catch (InterruptedException e) {
-            JOptionPane.showMessageDialog(null, "Error occurred during fixing");
-        }
-
-    }
-
-    public void addFixVariants(List<List<PTWay>> fixVariants) {
-        layer.addFixVariants(fixVariants);
-    }
-
-    public void clearFixVariants() {
-        layer.clearFixVariants();
-    }
-
-    public List<PTWay> getFixVariant(Character c) {
-        return layer.getFixVariant(c);
-    }
-
-    @SuppressWarnings("unused")
-    private void performDummyTest(Relation r) {
-        List<Relation> primitives = new ArrayList<>(1);
-        primitives.add(r);
-        Builder builder = TestError.builder(this, Severity.WARNING, ERROR_CODE_DIRECTION);
-        builder.message(tr("PT: dummy test warning"));
-        builder.primitives(primitives);
-        errors.add(
-                builder.build());
-    }
+	public static final int ERROR_CODE_SORTING = 3711;
+	public static final int ERROR_CODE_ROAD_TYPE = 3721;
+	public static final int ERROR_CODE_CONSTRUCTION = 3722;
+	public static final int ERROR_CODE_DIRECTION = 3731;
+	public static final int ERROR_CODE_END_STOP = 3741;
+	public static final int ERROR_CODE_SPLIT_WAY = 3742;
+	public static final int ERROR_CODE_RELAITON_MEMBER_ROLES = 3743;
+	public static final int ERROR_CODE_SOLITARY_STOP_POSITION = 3751;
+	public static final int ERROR_CODE_PLATFORM_PART_OF_HIGHWAY = 3752;
+	public static final int ERROR_CODE_STOP_NOT_SERVED = 3753;
+	public static final int ERROR_CODE_STOP_BY_STOP = 3754;
+	public static final int ERROR_CODE_NOT_PART_OF_STOP_AREA = 3761;
+	public static final int ERROR_CODE_STOP_AREA_NO_STOPS = 3762;
+	public static final int ERROR_CODE_STOP_AREA_NO_PLATFORM = 3763;
+	public static final int ERROR_CODE_STOP_AREA_COMPARE_RELATIONS = 3764;
+
+	private PTAssistantLayer layer;
+
+	public PTAssistantValidatorTest() {
+		super(tr("Public Transport Assistant tests"),
+				tr("Check if route relations are compatible with public transport version 2"));
+
+		layer = PTAssistantLayer.getLayer();
+		DataSet.addSelectionListener(layer);
+
+	}
+
+	@Override
+	public void visit(Node n) {
+
+		if (n.isIncomplete()) {
+			return;
+		}
+
+		NodeChecker nodeChecker = new NodeChecker(n, this);
+
+		// select only stop_positions
+		if (n.hasTag("public_transport", "stop_position")) {
+
+			// check if stop positions are on a way:
+			nodeChecker.performSolitaryStopPositionTest();
+
+			if (Main.pref.getBoolean("pt_assistant.stop-area-tests", true) == true) {
+				// check if stop positions are in any stop_area relation:
+				nodeChecker.performNodePartOfStopAreaTest();
+			}
+
+		}
+
+		// select only platforms
+		if (n.hasTag("public_transport", "platform")) {
+
+			// check that platforms are not part of any way:
+			nodeChecker.performPlatformPartOfWayTest();
+
+			if (Main.pref.getBoolean("pt_assistant.stop-area-tests", true) == true) {
+				// check if platforms are in any stop_area relation:
+				nodeChecker.performNodePartOfStopAreaTest();
+			}
+
+		}
+
+		this.errors.addAll(nodeChecker.getErrors());
+
+	}
+
+	@Override
+	public void visit(Relation r) {
+
+		// Download incomplete members. If the download does not work, return
+		// and do not do any testing.
+		if (r.hasIncompleteMembers()) {
+
+			boolean downloadSuccessful = this.downloadIncompleteMembers();
+			if (!downloadSuccessful) {
+				return;
+			}
+		}
+
+		if (r.hasIncompleteMembers()) {
+			return;
+		}
+
+		// Do some testing on stop area relations
+		if (Main.pref.getBoolean("pt_assistant.stop-area-tests", true) == true && StopUtils.isStopArea(r)) {
+
+			StopChecker stopChecker = new StopChecker(r, this);
+
+			// Check if stop area relation has one stop position.
+			stopChecker.performStopAreaStopPositionTest();
+
+			// Check if stop area relation has one platform.
+			stopChecker.performStopAreaPlatformTest();
+
+			// Check if stop position(s) belong the same route relation as
+			// related platform(s)
+			stopChecker.performStopAreaRelationsTest();
+
+			// Attach thrown errors
+			this.errors.addAll(stopChecker.getErrors());
+		}
+
+		if (!RouteUtils.isTwoDirectionRoute(r)) {
+			return;
+		}
+
+		// Check individual ways using the oneway direction test and the road
+		// type test:
+		WayChecker wayChecker = new WayChecker(r, this);
+		wayChecker.performDirectionTest();
+		wayChecker.performRoadTypeTest();
+		this.errors.addAll(wayChecker.getErrors());
+
+		proceedWithSorting(r);
+
+		// This allows to modify the route before the sorting and
+		// SegmentChecker are carried out:
+		// if (this.errors.isEmpty()) {
+		// proceedWithSorting(r);
+		// } else {
+		// this.proceedAfterWayCheckerErrors(r);
+		// }
+
+	}
+
+	/**
+	 * Downloads incomplete relation members in an extra thread (user input
+	 * required)
+	 *
+	 * @return true if successful, false if not successful
+	 */
+	private boolean downloadIncompleteMembers() {
+
+		final int[] userSelection = { 0 };
+
+		try {
+
+			if (SwingUtilities.isEventDispatchThread()) {
+
+				userSelection[0] = showIncompleteMembersDownloadDialog();
+
+			} else {
+
+				SwingUtilities.invokeAndWait(new Runnable() {
+					@Override
+					public void run() {
+						try {
+							userSelection[0] = showIncompleteMembersDownloadDialog();
+						} catch (InterruptedException e) {
+							e.printStackTrace();
+						}
+
+					}
+				});
+
+			}
+
+		} catch (InterruptedException | InvocationTargetException e) {
+			return false;
+		}
+
+		if (userSelection[0] == JOptionPane.YES_OPTION) {
+
+			Thread t = new IncompleteMembersDownloadThread();
+			t.start();
+			synchronized (t) {
+				try {
+					t.wait();
+				} catch (InterruptedException e) {
+					return false;
+				}
+			}
+
+		}
+
+		return true;
+
+	}
+
+	/**
+	 * Shows the dialog asking the user about an incomplete member download
+	 *
+	 * @return user's selection
+	 * @throws InterruptedException
+	 *             if interrupted
+	 */
+	private int showIncompleteMembersDownloadDialog() throws InterruptedException {
+
+		if (Main.pref.getBoolean("pt_assistant.download-incomplete", false) == true) {
+			return JOptionPane.YES_OPTION;
+		}
+
+		if (Main.pref.getBoolean("pt_assistant.download-incomplete", false) == false) {
+			return JOptionPane.NO_OPTION;
+		}
+
+		IncompleteMembersDownloadDialog incompleteMembersDownloadDialog = new IncompleteMembersDownloadDialog();
+		return incompleteMembersDownloadDialog.getUserSelection();
+
+	}
+
+	/**
+	 * Gets user input after errors were detected by WayChecker. Although this
+	 * method is not used in the current implementation, it can be used to fix
+	 * errors from the previous testing stage and modify the route before the
+	 * second stage of testing is carried out.
+	 */
+	@SuppressWarnings("unused")
+	private void proceedAfterWayCheckerErrors(Relation r) {
+
+		// count errors of each type:
+		int numberOfDirectionErrors = 0;
+		int numberOfRoadTypeErrors = 0;
+		for (TestError e : this.errors) {
+			if (e.getCode() == ERROR_CODE_DIRECTION) {
+				numberOfDirectionErrors++;
+			}
+			if (e.getCode() == ERROR_CODE_ROAD_TYPE) {
+				numberOfRoadTypeErrors++;
+			}
+		}
+
+		final int[] userInput = { 0 };
+		final long idParameter = r.getId();
+		final int directionErrorParameter = numberOfDirectionErrors;
+		final int roadTypeErrorParameter = numberOfRoadTypeErrors;
+
+		if (SwingUtilities.isEventDispatchThread()) {
+
+			userInput[0] = showProceedDialog(idParameter, directionErrorParameter, roadTypeErrorParameter);
+
+		} else {
+
+			try {
+				SwingUtilities.invokeAndWait(new Runnable() {
+					@Override
+					public void run() {
+						userInput[0] = showProceedDialog(idParameter, directionErrorParameter, roadTypeErrorParameter);
+
+					}
+				});
+			} catch (InvocationTargetException | InterruptedException e1) {
+				e1.printStackTrace();
+			}
+
+		}
+
+		if (userInput[0] == 0) {
+			this.fixErrorFromPlugin(this.errors);
+			proceedWithSorting(r);
+			return;
+		}
+
+		if (userInput[0] == 1) {
+			JOptionPane.showMessageDialog(null, "This is not implemented yet!");
+			return;
+		}
+
+		if (userInput[0] == 2) {
+			proceedWithSorting(r);
+		}
+
+		// if userInput==-1 (i.e. no input), do nothing and stop testing of the
+		// route.
+
+	}
+
+	private int showProceedDialog(long id, int numberOfDirectionErrors, int numberOfRoadTypeErrors) {
+
+		if (numberOfDirectionErrors == 0 && numberOfRoadTypeErrors == 0) {
+			return 2;
+		}
+
+		if (Main.pref.getBoolean("pt_assistant.proceed-without-fix", true) == false) {
+			return 0;
+		}
+
+		if (Main.pref.getBoolean("pt_assistant.proceed-without-fix", true) == true) {
+			return 2;
+		}
+
+		ProceedDialog proceedDialog = new ProceedDialog(id, numberOfDirectionErrors, numberOfRoadTypeErrors);
+		return proceedDialog.getUserSelection();
+
+	}
+
+	/**
+	 * Carries out the second stage of the testing: sorting
+	 *
+	 * @param r
+	 *            relation
+	 */
+	private void proceedWithSorting(Relation r) {
+
+		// Check if the relation is correct, or only has a wrong sorting order:
+		RouteChecker routeChecker = new RouteChecker(r, this);
+		routeChecker.performSortingTest();
+		List<TestError> routeCheckerErrors = routeChecker.getErrors();
+
+		/*- At this point, there are 3 variants:
+		 *
+		 * 1) There are no errors => route is correct
+		 * 2) There is only a sorting error (can only be 1), but otherwise
+		 * correct.
+		 * 3) There are some other errors/gaps that cannot be fixed by
+		 * sorting => start further test (stop-by-stop)
+		 *
+		 * */
+
+		if (!routeCheckerErrors.isEmpty()) {
+			// Variant 2
+			// If there is only the sorting error, add it
+			this.errors.addAll(routeChecker.getErrors());
+		}
+
+		// if (!routeChecker.getHasGap()) {
+		// // Variant 1
+		// storeCorrectRouteSegments(r);
+		// }
+
+		// Variant 3:
+		proceedAfterSorting(r);
+
+	}
+
+	/**
+	 * Carries out the stop-by-stop testing which includes building the route
+	 * data model.
+	 *
+	 * @param r
+	 *            route relation
+	 */
+	private void proceedAfterSorting(Relation r) {
+
+		SegmentChecker segmentChecker = new SegmentChecker(r, this);
+
+		// Check if the creation of the route data model in the segment checker
+		// worked. If it did not, it means the roles in the route relation do
+		// not match the tags of the route members.
+		if (!segmentChecker.getErrors().isEmpty()) {
+			this.errors.addAll(segmentChecker.getErrors());
+		}
+
+		segmentChecker.performFirstStopTest();
+		segmentChecker.performLastStopTest();
+		segmentChecker.performStopNotServedTest();
+
+		boolean sortingErrorFound = false;
+		for (TestError error : this.errors) {
+			if (error.getCode() == ERROR_CODE_SORTING) {
+				sortingErrorFound = true;
+				break;
+			}
+		}
+		if (!sortingErrorFound) {
+			segmentChecker.performStopByStopTest();
+			segmentChecker.findFixes();
+		}
+
+		for (TestError error : segmentChecker.getErrors()) {
+			if (error.getCode() != PTAssistantValidatorTest.ERROR_CODE_RELAITON_MEMBER_ROLES) {
+				this.errors.add(error);
+			}
+		}
+	}
+
+	/**
+	 * Method is called after all primitives has been visited, overrides the
+	 * method of the superclass.
+	 */
+	public void endTest() {
+		
+		// modify the error messages for the stop-by-stop test:
+		SegmentChecker.modifyStopByStopErrorMessages();
+
+		// add the stop-by-stop errors with modified messages:
+		for (Entry<Builder, PTRouteSegment> entry : SegmentChecker.wrongSegmentBuilders.entrySet()) {
+			TestError error = entry.getKey().build();
+			SegmentChecker.wrongSegments.put(error, entry.getValue());
+			this.errors.add(error);
+		}
+		
+		// reset the static collections in SegmentChecker:
+		SegmentChecker.reset();
+
+		super.endTest();
+
+	}
+
+	/**
+	 * Creates the PTRouteSegments of a route that has been found correct and
+	 * stores them in the list of correct route segments
+	 *
+	 * @param r
+	 *            route relation
+	 */
+	@SuppressWarnings("unused")
+	private void storeCorrectRouteSegments(Relation r) {
+		PTRouteDataManager manager = new PTRouteDataManager(r);
+		StopToWayAssigner assigner = new StopToWayAssigner(manager.getPTWays());
+		if (manager.getPTStops().size() > 1) {
+			for (int i = 1; i < manager.getPTStops().size(); i++) {
+				PTStop segmentStartStop = manager.getPTStops().get(i - 1);
+				PTStop segmentEndStop = manager.getPTStops().get(i);
+				Way segmentStartWay = assigner.get(segmentStartStop);
+				Way segmentEndWay = assigner.get(segmentEndStop);
+				List<PTWay> waysBetweenStops = manager.getPTWaysBetween(segmentStartWay, segmentEndWay);
+				PTRouteSegment routeSegment = new PTRouteSegment(segmentStartStop, segmentEndStop, waysBetweenStops, r);
+				SegmentChecker.addCorrectSegment(routeSegment);
+			}
+		}
+	}
+
+	/**
+	 * Checks if the test error is fixable
+	 */
+	@Override
+	public boolean isFixable(TestError testError) {
+		if (testError.getCode() == ERROR_CODE_DIRECTION || testError.getCode() == ERROR_CODE_ROAD_TYPE
+				|| testError.getCode() == ERROR_CODE_CONSTRUCTION || testError.getCode() == ERROR_CODE_SORTING
+				|| testError.getCode() == PTAssistantValidatorTest.ERROR_CODE_SOLITARY_STOP_POSITION
+				|| testError.getCode() == PTAssistantValidatorTest.ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) {
+			return true;
+		}
+
+		if (testError.getCode() == ERROR_CODE_STOP_BY_STOP && SegmentChecker.isFixable(testError)) {
+			return true;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Fixes the given error
+	 */
+	@Override
+	public Command fixError(TestError testError) {
+
+		// repaint the relation in the pt_assistant layer:
+		if (testError.getPrimitives().iterator().next().getType().equals(OsmPrimitiveType.RELATION)) {
+			Relation relationToBeFixed = (Relation) testError.getPrimitives().iterator().next();
+			this.layer.repaint(relationToBeFixed);
+		}
+
+		// reset the last fix:
+		PTAssistantPlugin.setLastFix(null);
+
+		List<Command> commands = new ArrayList<>();
+
+		if (testError.getCode() == ERROR_CODE_ROAD_TYPE || testError.getCode() == ERROR_CODE_CONSTRUCTION) {
+			commands.add(WayChecker.fixErrorByZooming(testError));
+		}
+
+		if (testError.getCode() == ERROR_CODE_DIRECTION) {
+			commands.add(WayChecker.fixErrorByZooming(testError));
+
+		}
+
+		if (testError.getCode() == ERROR_CODE_SORTING) {
+			commands.add(RouteChecker.fixSortingError(testError));
+		}
+
+		if (testError.getCode() == ERROR_CODE_SOLITARY_STOP_POSITION
+				|| testError.getCode() == ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) {
+			commands.add(NodeChecker.fixError(testError));
+		}
+
+		if (testError.getCode() == ERROR_CODE_STOP_BY_STOP) {
+			commands.add(SegmentChecker.fixError(testError));
+			// make sure the primitives of this testError are selected:
+			Collection<OsmPrimitive> primitivesToSelect = new ArrayList<>();
+			for (Object obj : testError.getPrimitives()) {
+				primitivesToSelect.add((OsmPrimitive) obj);
+			}
+			SelectCommand selectCommand = new SelectCommand(primitivesToSelect);
+			SwingUtilities.invokeLater(new Runnable() {
+				@Override
+				public void run() {
+					selectCommand.executeCommand();
+				}
+			});
+		}
+
+		if (commands.isEmpty()) {
+			return null;
+		}
+
+		if (commands.size() == 1) {
+			return commands.get(0);
+		}
+
+		return new SequenceCommand(tr("Fix error"), commands);
+	}
+
+	/**
+	 * This method is the counterpart of the fixError(TestError testError)
+	 * method. The fixError method is invoked from the core validator (e.g. when
+	 * user presses the "Fix" button in the validator). This method is invoken
+	 * when the fix is initiated from within the plugin (e.g. automated fixes).
+	 */
+	private void fixErrorFromPlugin(List<TestError> testErrors) {
+
+		// run fix task asynchronously
+		FixTask fixTask = new FixTask(testErrors);
+
+		Thread t = new Thread(fixTask);
+		t.start();
+		try {
+			t.join();
+			errors.removeAll(testErrors);
+
+		} catch (InterruptedException e) {
+			JOptionPane.showMessageDialog(null, "Error occurred during fixing");
+		}
+
+	}
+
+	public void addFixVariants(List<List<PTWay>> fixVariants) {
+		layer.addFixVariants(fixVariants);
+	}
+
+	public void clearFixVariants() {
+		layer.clearFixVariants();
+	}
+
+	public List<PTWay> getFixVariant(Character c) {
+		return layer.getFixVariant(c);
+	}
+
+	@SuppressWarnings("unused")
+	private void performDummyTest(Relation r) {
+		List<Relation> primitives = new ArrayList<>(1);
+		primitives.add(r);
+		Builder builder = TestError.builder(this, Severity.WARNING, ERROR_CODE_DIRECTION);
+		builder.message(tr("PT: dummy test warning"));
+		builder.primitives(primitives);
+		errors.add(builder.build());
+	}
 
 }
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java	(revision 33107)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java	(revision 33108)
@@ -296,9 +296,7 @@
 			Node firstNode = findFirstNodeOfRouteSegmentInDirectionOfTravel(segmentWays.get(0));
 
-			// get last added TestErrorBuilder:
-
 			if (firstNode == null) {
 				// check if this error has just been reported:
-				if (wrongSegmentBuilders.isEmpty() && lastCreatedBuilderHighlighted.size() == 1
+				if (wrongSegmentBuilders.isEmpty() && lastCreatedBuilderHighlighted != null && lastCreatedBuilderHighlighted.size() == 1
 						&& lastCreatedBuilderHighlighted.get(0) == startWay) {
 					// do nothing, this error has already been reported in
